我想删除if..else
和compMove
函数中的winCon
语句,以使用一种算法。
我尝试将if
语句条件切换为if(board[z] == 'X' && board[z+1] == 'X' && board[z+2] == 'X' ....)
,这无效。
我当时在想switch
可能会在其中发挥作用,或者我需要找到一种在板上找到相邻方块的方法。
我将从哪里开始?
#include <iostream>
#include <time.h>
using namespace std;
int moves = 0, defBoard[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, playerSpace, x;
char board[] = { '-', '-', '-', '-', '-', '-', '-', '-', '-', }, play;
bool gameOver = false;
void playerMove(), compMove(), print(), winCon(), ticTacToe(), nuclearWar();
int random(int);
int main(){
cout << "Shall we Play a Game? Y/N" << endl;
cin >> play;
if (play == 'N' || play == 'n'){
return 0;
}
else if (play == 'Y' || play == 'y'){
cout << "1. Global Thermal Nuclear War" << endl << "2. Tic-Tac-Toe" << endl;
cin >> x;
switch (x){
case 1:
nuclearWar();
break;
case 2:
ticTacToe();
cout << "Shall we another Play a Game? Y/N" << endl;
cin >> x;
break;
}
}
else{
cout << "Invalid Responce." << endl;
cout << "Shutting Down..." << endl;
return 0;
}
return 0;
}
void print(){
cout << "Total Turns: " << moves << endl;
for (int i = 0; i != 9; ++i){
if ((i + 1) % 3 == 0){
cout << board[i] << " " << endl;
}
else{
cout << board[i] << " ";
}
}
cout << endl;
}
void playerMove(){
cout << "Select Move" << endl;
cin >> playerSpace;
if (board[playerSpace - 1] == '-' && board[playerSpace - 1] != 'O'){
board[playerSpace - 1] = 'X';
}
else{
cout << "Invalid Move " << endl;
playerMove();
}
moves++;
if (moves == 5){
print();
}
else{
compMove();
print();
}
}
void compMove(){
if (board[4] == '-'){
board[4] = 'O';
}
else if (board[0] == 'X' && board[1] == 'X' && board[2] == '-'){
board[2] = 'O';
}
else if (board[0] == 'X' && board[2] == 'X' && board[1] == '-'){
board[1] = 'O';
}
else if (board[1] == 'X' && board[2] == 'X' && board[0] == '-'){
board[0] = 'O';
}
else if (board[3] == 'X' && board[4] == 'X' && board[5] == '-'){
board[5] = 'O';
}
else if (board[3] == 'X' && board[5] == 'X' && board[4] == '-'){
board[4] = 'O';
}
else if (board[4] == 'X' && board[5] == 'X' && board[3] == '-'){
board[3] = 'O';
}
else if (board[6] == 'X' && board[7] == 'X' && board[8] == '-'){
board[8] = 'O';
}
else if (board[6] == 'X' && board[8] == 'X' && board[7] == '-'){
board[7] = 'O';
}
else if (board[7] == 'X' && board[8] == 'X' && board[6] == '-'){
board[6] = 'O';
}
else if (board[0] == 'X' && board[3] == 'X' && board[6] == '-'){
board[6] = 'O';
}
else if (board[0] == 'X' && board[6] == 'X' && board[3] == '-'){
board[3] = 'O';
}
else if (board[3] == 'X' && board[6] == 'X' && board[0] == '-'){
board[0] = 'O';
}
else if (board[1] == 'X' && board[4] == 'X' && board[7] == '-'){
board[7] = 'O';
}
else if (board[1] == 'X' && board[7] == 'X' && board[4] == '-'){
board[4] = 'O';
}
else if (board[4] == 'X' && board[7] == 'X' && board[1] == '-'){
board[1] = 'O';
}
else if (board[2] == 'X' && board[5] == 'X' && board[8] == '-'){
board[8] = 'O';
}
else if (board[2] == 'X' && board[8] == 'X' && board[5] == '-'){
board[5] = 'O';
}
else if (board[5] == 'X' && board[8] == 'X' && board[2] == '-'){
board[2] = 'O';
}
else if (board[0] == 'X' && board[5] == 'X' && board[8] == '-'){
board[8] = 'O';
}
else if (board[8] == 'X' && board[5] == 'X' && board[0] == '-'){
board[0] = 'O';
}
else if (board[2] == 'X' && board[5] == 'X' && board[6] == '-'){
board[6] = 'O';
}
else if (board[6] == 'X' && board[5] == 'X' && board[2] == '-'){
board[2] = 'O';
}
else{
int val = random(9);
if (board[val - 1] == '-'){
board[val - 1] = 'O';
}
else{
compMove();
}
}
}
void winCon(){
if (board[0] == 'X' && board[1] == 'X' && board[2] == 'X' || board[3] == 'X' && board[4] == 'X' && board[5] == 'X' ||
board[6] == 'X' && board[7] == 'X' && board[8] == 'X' || board[0] == 'X' && board[3] == 'X' && board[6] == 'X' ||
board[1] == 'X' && board[4] == 'X' && board[7] == 'X' || board[2] == 'X' && board[5] == 'X' && board[8] == 'X' ||
board[0] == 'X' && board[4] == 'X' && board[8] == 'X' || board[2] == 'X' && board[4] == 'X' && board[6] == 'X'){
cout << "Player Wins! " << endl;
gameOver = true;
}
else if (board[0] == 'O' && board[1] == 'O' && board[2] == 'O' || board[3] == 'O' && board[4] == 'O' && board[5] == 'O' ||
board[6] == 'O' && board[7] == 'O' && board[8] == 'O' || board[0] == 'O' && board[3] == 'O' && board[6] == 'O' ||
board[1] == 'O' && board[4] == 'O' && board[7] == 'O' || board[2] == 'O' && board[5] == 'O' && board[8] == 'O' ||
board[0] == 'O' && board[5] == 'O' && board[8] == 'O' || board[2] == 'O' && board[5] == 'O' && board[6] == 'O'){
cout << "Computer Wins! " << endl;
gameOver = true;
}
else if (moves == 5){
cout << "Tie Game. " << endl;
gameOver = true;
}
else{
gameOver = false;
}
}
int random(int Max){
return rand() % Max + 1;
}
void ticTacToe(){
for (int i = 0; i != 9; ++i){
if ((i + 1) % 3 == 0){
cout << defBoard[i] << " " << endl;
}
else{
cout << defBoard[i] << " ";
}
}
srand(time(NULL));
while (gameOver == false){
playerMove();
winCon();
}
}
void nuclearWar(){
srand(time(NULL));
int val = random(4);
switch (val){
case 1:
cout << "A strange game. The only winning move is not to play. How about a nice game of chess?" << endl;
break;
case 2:
cout << "I've come to the conclusion that your new defense system sucks." << endl;
break;
case 3:
cout << "Flush the bombers, get the subs in launch mode. We are at DEFCON 1." << endl;
break;
case 4:
cout << " Is it a game... or is it real?" << endl;
break;
}
}
答案 0 :(得分:0)
您可能首先注意到winCon
中的类似代码:
void winCon(){
if (board[0] == 'X' && board[1] == 'X' && board[2] == 'X' || board[3] == 'X' && board[4] == 'X' && board[5] == 'X' ||
board[6] == 'X' && board[7] == 'X' && board[8] == 'X' || board[0] == 'X' && board[3] == 'X' && board[6] == 'X' ||
board[1] == 'X' && board[4] == 'X' && board[7] == 'X' || board[2] == 'X' && board[5] == 'X' && board[8] == 'X' ||
board[0] == 'X' && board[4] == 'X' && board[8] == 'X' || board[2] == 'X' && board[4] == 'X' && board[6] == 'X'){
cout << "Player Wins! " << endl;
gameOver = true;
}
else if (board[0] == 'O' && board[1] == 'O' && board[2] == 'O' || board[3] == 'O' && board[4] == 'O' && board[5] == 'O' ||
board[6] == 'O' && board[7] == 'O' && board[8] == 'O' || board[0] == 'O' && board[3] == 'O' && board[6] == 'O' ||
board[1] == 'O' && board[4] == 'O' && board[7] == 'O' || board[2] == 'O' && board[5] == 'O' && board[8] == 'O' ||
board[0] == 'O' && board[5] == 'O' && board[8] == 'O' || board[2] == 'O' && board[5] == 'O' && board[6] == 'O'){
cout << "Computer Wins! " << endl;
gameOver = true;
}
else if (moves == 5){
cout << "Tie Game. " << endl;
gameOver = true;
}
else{
gameOver = false;
}
}
类似,但有错字。让我们通过执行专用功能来解决该问题:
bool has_won(const char (&board)[9], char p)
{
return board[0] == p && board[1] == p && board[2] == p
|| board[3] == p && board[4] == p && board[5] == p
|| board[6] == p && board[7] == p && board[8] == p
|| board[0] == p && board[3] == p && board[6] == p
|| board[1] == p && board[4] == p && board[7] == p
|| board[2] == p && board[5] == p && board[8] == p
|| board[0] == p && board[4] == p && board[8] == p
|| board[2] == p && board[4] == p && board[6] == p;
}
void winCon(){
if (has_won(board, 'X')) {
cout << "Player Wins! " << endl;
gameOver = true;
}
else if (has_won(board, 'O')){
cout << "Computer Wins! " << endl;
gameOver = true;
} else if (moves == 5){
cout << "Tie Game. " << endl;
gameOver = true;
} else{
gameOver = false;
}
}
然后使用has_won
函数,有几种拆分方法。
我们可能会注意到我们先水平检查,然后垂直检查2条对角线。
我们可能会注意到三元组遵循我们可能分解的某些规则/系列。
所以我们可以这样做:
bool three_in_a_row(const char (&board)[9], char p, int origin, int dir)
{
#if 1
return board[origin] == p && board[origin + dir] == p && board[origin + 2 dir] == p;
#else
for (int i = 0; i != 3; ++i) {
if (board[origin + i * dir] != p) {
return false;
}
}
return true;
#endif
}
// Is three_in_a_row(board, p, 0, 3) "better" than board[0] == p && board[3] == p && board[6] == p
bool has_won(const char (&board)[9], char p)
{
// horizontals and verticals
for (int i = 0; i != 3; ++i) {
if (three_in_a_row(board, p, 3 * i, 1) // 3 * i, 3 * i + 1, 3 * i + 2
|| three_in_a_row(board, p, i, 3)) { // i, i + 3, i + 6
return true;
}
}
// both diagonals
return three_in_a_row(board, p, 0, 4) // 0 4 8
|| three_in_a_row(board, p, 2, 2); // 2 4 6
}
尽管第一次分解可使代码更简洁,但第二次尝试尚不清楚。 (此外,我们添加了一些隐藏的依赖项:对起点/方向应该正确,否则我们可能会超出范围)
答案 1 :(得分:0)
通过使用行和列索引将board
更改为二维数组以访问单个单元格,并更智能地跟踪X和O使用多少个单元格,可以大大简化代码。
尝试更多类似的方法:
#include <iostream>
#include <ctime>
using namespace std;
struct counts{
int NumX;
int NumO;
void reset(){
NumX = NumO = 0;
}
void added(char which){
switch (which){
case 'X': ++NumX; break;
case 'O': ++NumO; break;
}
}
};
int moves, number;
char board[3][3], letter;
counts rows[3], cols[3], diagonals[2];
int cellsAvailable[9], numAvailable;
void playerMove();
void compMove();
void print();
bool gameOver();
void ticTacToe();
void nuclearWar();
int random(int);
void setCell(int, int, char);
int main(){
srand(time(NULL));
cout << "Shall we Play a Game? Y/N" << endl;
do {
cin >> letter;
if (letter == 'N' || letter == 'n'){
break;
}
if (letter != 'Y' && letter != 'y'){
cout << "Invalid Response." << endl;
cout << "Shutting Down..." << endl;
break;
}
cout << "1. Global Thermal Nuclear War" << endl
<< "2. Tic-Tac-Toe" << endl;
cin >> number;
switch (number){
case 1:
nuclearWar();
break;
case 2:
ticTacToe();
break;
default:
cout << "Invalid Game." << endl;
break;
}
cout << "Shall we Play another Game? Y/N" << endl;
}
while (true);
return 0;
}
void print(){
cout << "Total Turns: " << moves << endl;
for (int row = 0; row < 3; ++row){
for (int col = 0; col < 3; ++col){
cout << board[row][col] << " ";
}
cout << endl;
}
cout << endl;
}
void setCell(int row, int col, char which){
board[row][col] = which;
rows[row].added(which);
cols[col].added(which);
if (row == col){
diagonals[0].added(which);
}
if ((row == 0 && col == 2) ||
(row == 1 && col == 1) ||
(row == 2 && col == 0)){
diagonals[1].added(which);
}
int val = (row * 3) + col;
for(int i = 0; i < numAvailable; ++i){
if (cellsAvailable[i] == val){
for(int j = i + 1; j < numAvailable; ++j){
cellsAvailable[j-1] = cellsAvailable[j];
}
--numAvailable;
break;
}
}
}
void playerMove(){
do {
cout << "Select Move" << endl;
cin >> number;
if (number >= 1 && number <= 9){
--number;
int row = number / 3;
int col = number % 3;
if (board[row][col] == '-'){
setCell(row, col, 'X');
break;
}
}
cout << "Invalid Move" << endl;
}
while (true);
}
void compMove(){
for (int row = 0; row < 3; ++row){
if (rows[row].NumX == 2 && rows[row].NumO == 0){
for(int col = 0; col < 3; ++col){
if (board[row][col] == '-'){
setCell(row, col, 'O');
break;
}
}
return;
}
}
for (int col = 0; col < 3; ++col){
if (cols[col].NumX == 2 && cols[col].NumO == 0){
for(int row = 0; row < 3; ++row){
if (board[row][col] == '-'){
setCell(row, col, 'O');
break;
}
}
return;
}
}
if (diagonals[0].NumX == 2 && diagonals[0].NumO == 0){
for(int row = 0; row < 3; ++row){
for(int col = 0; col < 3; ++col){
if (board[row][col] == '-'){
setCell(row, col, 'O');
break;
}
}
}
return;
}
if (diagonals[1].NumX == 2 && diagonals[1].NumO == 0){
for(int row = 0; row < 3; ++row){
for(int col = 2; col >= 0; --col){
if (board[row][col] == '-'){
setCell(row, col, 'O');
break;
}
}
}
return;
}
int val = cellsAvailable[random(numAvailable)];
setCell(val / 3, val % 3, 'O');
}
bool gameOver(){
for(int i = 0; i < 3; ++i){
if (rows[i].NumX == 3 || cols[i].NumX == 3 || (i < 2 && diagonals[i].NumX == 3)){
cout << "Player Wins!" << endl;
return true;
}
if (rows[i].NumO == 3 || cols[i].NumO == 3 || (i < 2 && diagonals[i].NumO == 3)){
cout << "Computer Wins!" << endl;
return true;
}
}
if (moves == 5){
cout << "Tie Game." << endl;
return true;
}
return false;
}
int random(int Max){
return rand() % Max;
}
void ticTacToe(){
for (int row = 0; row < 3; ++row){
for (int col = 0; col < 3; ++col) {
board[row][col] = '-';
cout << ((row * 3) + col) + 1 << " ";
}
cout << endl;
}
for (int i = 0; i < 3; ++i){
rows[i].reset();
cols[i].reset();
}
for (int i = 0; i < 2; ++i){
diagonals[i].reset();
}
for(int i = 0; i < 9; ++i){
cellsAvailable[i] = i;
}
numAvailable = 9;
moves = 0;
do{
playerMove();
if (++moves != 5){
compMove();
}
print();
}
while (!gameOver());
}
void nuclearWar(){
int val = random(4) + 1;
switch (val){
case 1:
cout << "A strange game. The only winning move is not to play. How about a nice game of chess?" << endl;
break;
case 2:
cout << "I've come to the conclusion that your new defense system sucks." << endl;
break;
case 3:
cout << "Flush the bombers, get the subs in launch mode. We are at DEFCON 1." << endl;
break;
case 4:
cout << " Is it a game... or is it real?" << endl;
break;
}
}