Add existing files to Git
This commit is contained in:
parent
73d24e7748
commit
0c5991fa20
7
.vscode/launch.json
vendored
Normal file
7
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": []
|
||||
}
|
||||
206
src/board.rs
206
src/board.rs
@ -11,6 +11,14 @@ pub struct Board {
|
||||
impl fmt::Display for Board {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let horiz_sep_line = "-".repeat(BOARD_SIZE * 2 + 1);
|
||||
|
||||
// Print numbers at top so I can read the board easier
|
||||
write!(f, " ")?;
|
||||
for j in 0..BOARD_SIZE {
|
||||
write!(f, "{} ", j)?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
|
||||
for i in 0..BOARD_SIZE {
|
||||
writeln!(f, " {}", horiz_sep_line)?;
|
||||
|
||||
@ -24,12 +32,26 @@ impl fmt::Display for Board {
|
||||
}
|
||||
writeln!(f)?;
|
||||
}
|
||||
|
||||
// put a line at the bottom of the board too
|
||||
writeln!(f, "{}", horiz_sep_line)?;
|
||||
writeln!(f, " {}", horiz_sep_line)?;
|
||||
|
||||
// Print the current score
|
||||
let (white_score, black_score) = self.get_score();
|
||||
writeln!(f, "White Score: {}\nBlack Score: {}", white_score, black_score);
|
||||
|
||||
// Print game over screen
|
||||
if self.game_over() == true {
|
||||
match self.get_winner() {
|
||||
Some(Piece::Black) => writeln!(f, "Black Wins"),
|
||||
Some(Piece::White) => writeln!(f, "White Wins"),
|
||||
None => writeln!(f, "Tie"),
|
||||
}?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
impl Board {
|
||||
@ -160,6 +182,56 @@ impl Board {
|
||||
}
|
||||
captured
|
||||
}
|
||||
|
||||
// keep score of each color
|
||||
pub fn get_score(&self) -> (usize, usize) {
|
||||
let mut white_score = 0;
|
||||
let mut black_score = 0;
|
||||
|
||||
for row in &self.board {
|
||||
for &cell in row {
|
||||
match cell {
|
||||
Some(Piece::White) => white_score += 1,
|
||||
Some(Piece::Black) => black_score += 1,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
(white_score, black_score)
|
||||
}
|
||||
|
||||
// Get the winning piece (for game over screen mainly)
|
||||
pub fn get_winner(&self) -> Option<Piece> {
|
||||
let (white_score, black_score) = self.get_score();
|
||||
|
||||
// White wins
|
||||
if white_score > black_score {
|
||||
Some(Piece::White)
|
||||
}
|
||||
|
||||
// Black Wins
|
||||
else if black_score > white_score {
|
||||
Some(Piece::Black)
|
||||
}
|
||||
|
||||
// Tie
|
||||
else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn game_over(&self) -> bool {
|
||||
let (white_score, black_score) = self.get_score();
|
||||
let max_score = BOARD_SIZE * BOARD_SIZE;
|
||||
let combined_score = black_score + white_score;
|
||||
|
||||
if max_score == combined_score {
|
||||
true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -262,4 +334,132 @@ mod test {
|
||||
|
||||
assert_eq!(board.place(2, 5, Piece::Black), Ok(()), "{}", board);
|
||||
}
|
||||
}
|
||||
|
||||
// Test corner capture from top-left corner
|
||||
#[test]
|
||||
fn corner_capture_top_left() {
|
||||
let mut board = Board::new();
|
||||
|
||||
// Black pieces at (0, 0) and (1, 0), and (0, 1) to create capture opportunity
|
||||
board.place_unchecked(0, 0, Piece::Black);
|
||||
board.place_unchecked(1, 0, Piece::White);
|
||||
board.place_unchecked(0, 1, Piece::White);
|
||||
|
||||
board.propegate_from(0, 0);
|
||||
|
||||
// Capture white piece at (0, 1) and (1, 0)
|
||||
assert_eq!(board.get(0, 1), &Some(Piece::Black));
|
||||
assert_eq!(board.get(1, 0), &Some(Piece::Black));
|
||||
}
|
||||
|
||||
// Test corner capture from top-right corner
|
||||
#[test]
|
||||
fn corner_capture_top_right() {
|
||||
let mut board = Board::new();
|
||||
|
||||
// Black pieces at (0, 7) and (1, 7), and (0, 6) to create capture opportunity
|
||||
board.place_unchecked(0, 7, Piece::Black);
|
||||
board.place_unchecked(1, 7, Piece::White);
|
||||
board.place_unchecked(0, 6, Piece::White);
|
||||
|
||||
board.propegate_from(0, 7);
|
||||
|
||||
// Capture white piece at (0, 6) and (1, 7)
|
||||
assert_eq!(board.get(0, 6), &Some(Piece::Black));
|
||||
assert_eq!(board.get(1, 7), &Some(Piece::Black));
|
||||
}
|
||||
|
||||
// Test corner capture from bottom-left corner
|
||||
#[test]
|
||||
fn corner_capture_bottom_left() {
|
||||
let mut board = Board::new();
|
||||
|
||||
// Black pieces at (7, 0) and (6, 0), and (7, 1) to create capture opportunity
|
||||
board.place_unchecked(7, 0, Piece::Black);
|
||||
board.place_unchecked(6, 0, Piece::White);
|
||||
board.place_unchecked(7, 1, Piece::White);
|
||||
|
||||
board.propegate_from(7, 0);
|
||||
|
||||
// Capture white piece at (7, 1) and (6, 0)
|
||||
assert_eq!(board.get(7, 1), &Some(Piece::Black));
|
||||
assert_eq!(board.get(6, 0), &Some(Piece::Black));
|
||||
}
|
||||
|
||||
// Test corner capture from bottom-right corner
|
||||
#[test]
|
||||
fn corner_capture_bottom_right() {
|
||||
let mut board = Board::new();
|
||||
|
||||
// Black pieces at (7, 7) and (6, 7), and (7, 6) to create capture opportunity
|
||||
board.place_unchecked(7, 7, Piece::Black);
|
||||
board.place_unchecked(6, 7, Piece::White);
|
||||
board.place_unchecked(7, 6, Piece::White);
|
||||
|
||||
board.propegate_from(7, 7);
|
||||
|
||||
// Capture white piece at (7, 6) and (6, 7)
|
||||
assert_eq!(board.get(7, 6), &Some(Piece::Black));
|
||||
assert_eq!(board.get(6, 7), &Some(Piece::Black));
|
||||
}
|
||||
|
||||
// Test capture from top-left corner (horizontal)
|
||||
#[test]
|
||||
fn capture_top_left_horiz() {
|
||||
let mut board = Board::new();
|
||||
|
||||
// Create a scenario where a capture should happen horizontally from (0, 0)
|
||||
board.place_unchecked(0, 0, Piece::Black);
|
||||
board.place_unchecked(0, 1, Piece::White);
|
||||
board.place_unchecked(0, 2, Piece::Black);
|
||||
|
||||
board.propegate_from(0, 2);
|
||||
|
||||
assert_eq!(board.get(0, 1), &Some(Piece::Black));
|
||||
}
|
||||
|
||||
// Test capture from top-right corner (horizontal)
|
||||
#[test]
|
||||
fn capture_top_right_horiz() {
|
||||
let mut board = Board::new();
|
||||
|
||||
// Create a scenario where a capture should happen horizontally from (0, 7)
|
||||
board.place_unchecked(0, 7, Piece::Black);
|
||||
board.place_unchecked(0, 6, Piece::White);
|
||||
board.place_unchecked(0, 5, Piece::Black);
|
||||
|
||||
board.propegate_from(0, 5);
|
||||
|
||||
assert_eq!(board.get(0, 6), &Some(Piece::Black));
|
||||
}
|
||||
|
||||
// Test capture from top-left corner (vertical)
|
||||
#[test]
|
||||
fn capture_top_left_vert() {
|
||||
let mut board = Board::new();
|
||||
|
||||
// Create a scenario where a capture should happen vertically from (0, 0)
|
||||
board.place_unchecked(0, 0, Piece::Black);
|
||||
board.place_unchecked(1, 0, Piece::White);
|
||||
board.place_unchecked(2, 0, Piece::Black);
|
||||
|
||||
board.propegate_from(2, 0);
|
||||
|
||||
assert_eq!(board.get(1, 0), &Some(Piece::Black));
|
||||
}
|
||||
|
||||
// Test capture from bottom-left corner (vertical)
|
||||
#[test]
|
||||
fn capture_bottom_left_vert() {
|
||||
let mut board = Board::new();
|
||||
|
||||
// Create a scenario where a capture should happen vertically from (7, 0)
|
||||
board.place_unchecked(7, 0, Piece::Black);
|
||||
board.place_unchecked(6, 0, Piece::White);
|
||||
board.place_unchecked(5, 0, Piece::Black);
|
||||
|
||||
board.propegate_from(5, 0);
|
||||
|
||||
assert_eq!(board.get(6, 0), &Some(Piece::Black));
|
||||
}
|
||||
}
|
||||
49
src/game.rs
49
src/game.rs
@ -1,5 +1,4 @@
|
||||
use crate::{agent::Agent, board::Board};
|
||||
use std::time::Duration;
|
||||
|
||||
pub struct Game {
|
||||
players: [Box<dyn Agent>; 2],
|
||||
@ -29,31 +28,59 @@ impl Game {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle when a move is made
|
||||
pub fn step(&mut self, player_i: usize) {
|
||||
let player_move = self.players[player_i].next_move(&self.board);
|
||||
if let Some((i, j)) = player_move {
|
||||
if let Ok(()) = self.board.place(i, j, self.players[player_i].color()) {
|
||||
let player_color = self.players[player_i].color();
|
||||
|
||||
loop {
|
||||
let player_move = self.players[player_i].next_move(&self.board);
|
||||
|
||||
if let Some((i, j)) = player_move {
|
||||
match self.board.place(i, j, player_color) {
|
||||
// Check if its a valid move
|
||||
Ok(_) => {
|
||||
println!("Player {} placed at ({}, {})", player_i, i, j);
|
||||
break;
|
||||
}
|
||||
|
||||
// Lets the player try again if the move is invalid
|
||||
// Now we dont need to restart the game if we mess up
|
||||
Err(err) => {
|
||||
println!("Invalid move by Player {}: {}. Try again.", player_i, err);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
todo!("handle invalid player move");
|
||||
println!("Player {} did not make a move!", player_i);
|
||||
return; // No valid move available
|
||||
}
|
||||
} else {
|
||||
panic!("player {} did not make a move", player_i);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO! make this loop good
|
||||
pub fn game_loop(&mut self) {
|
||||
let mut i = 0;
|
||||
let mut current_player: usize = 0;
|
||||
|
||||
loop {
|
||||
// alternate which player plays
|
||||
i += 1;
|
||||
i %= self.players.len();
|
||||
current_player += 1;
|
||||
current_player %= self.players.len();
|
||||
|
||||
println!("{}", self);
|
||||
|
||||
self.step(i);
|
||||
// Check if the game is over
|
||||
if self.board.game_over() == true {
|
||||
break;
|
||||
}
|
||||
|
||||
self.step(current_player);
|
||||
|
||||
// std::thread::sleep(Duration::from_millis(200));
|
||||
}
|
||||
// Print Game Over Screen
|
||||
println!("{}", self);
|
||||
match self.board.get_winner() {
|
||||
Some(winner) => println!("Game Over! {} Wins!", winner.text()),
|
||||
None => print!("It's a tie!! You either both suck or are both really good..."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user