本来有一个现成的程序,只不过是老版 C++/C 的,复制进 Visual Studio 2019 会报错:
然后修改了仍然不太好用,于是决定自己写一个,耗时1.5小时。
图形界面(鼠标控制)见我的博客:
【C++ 程序】 井字棋游戏(人 VS 人)(EasyX 图形界面)
人机版链接见文末 See also。
以下是程序:(分析见程序下面):
程序
//This program is a simple tic-tac-toe game.
#include <iostream>
#include <string>
#include <cstddef>
#include <stdexcept>
using namespace std;
char point_now[3][3] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
char player = 'X';
unsigned step_count = 0;
int win_lose(char point[3][3], int n)
{
if (point[0][0] == point[0][1] && point[0][1] == point[0][2] && point[0][0] == 'X') return 1; // X wins
if (point[1][0] == point[1][1] && point[1][1] == point[1][2] && point[1][0] == 'X') return 1; // X wins
if (point[2][0] == point[2][1] && point[2][1] == point[2][2] && point[2][0] == 'X') return 1; // X wins
if (point[0][0] == point[1][0] && point[1][0] == point[2][0] && point[0][0] == 'X') return 1; // X wins
if (point[0][1] == point[1][1] && point[1][1] == point[2][1] && point[0][1] == 'X') return 1; // X wins
if (point[0][2] == point[1][2] && point[1][2] == point[2][2] && point[0][2] == 'X') return 1; // X wins
if (point[0][0] == point[1][1] && point[1][1] == point[2][2] && point[1][1] == 'X') return 1; // X wins
if (point[0][2] == point[1][1] && point[1][1] == point[2][0] && point[1][1] == 'X') return 1; // X wins
if (point[0][0] == point[0][1] && point[0][1] == point[0][2] && point[0][0] == '0') return 2; // 0 wins
if (point[1][0] == point[1][1] && point[1][1] == point[1][2] && point[1][0] == '0') return 2; // 0 wins
if (point[2][0] == point[2][1] && point[2][1] == point[2][2] && point[2][0] == '0') return 2; // 0 wins
if (point[0][0] == point[1][0] && point[1][0] == point[2][0] && point[0][0] == '0') return 2; // 0 wins
if (point[0][1] == point[1][1] && point[1][1] == point[2][1] && point[0][1] == '0') return 2; // 0 wins
if (point[0][2] == point[1][2] && point[1][2] == point[2][2] && point[0][2] == '0') return 2; // 0 wins
if (point[0][0] == point[1][1] && point[1][1] == point[2][2] && point[1][1] == '0') return 2; // 0 wins
if (point[0][2] == point[1][1] && point[1][1] == point[2][0] && point[1][1] == '0') return 2; // 0 wins
if (n == 9) return 3; // end up in a draw
else return 0; // unfinished
}
void game_player_change(char &player)
{
if (player == 'X')
player = '0'; // X -> 0
else player = 'X';// 0 -> X
}
int main()
{
std::cout << "This program is a simple tic-tac-toe game.\nProgrammer:Teddy van Jerry\n" << endl;
// Print an empty board.
std::cout << "| |1|2|3|" << endl;
std::cout << "|A| | | |" << endl;
std::cout << "|B| | | |" << endl;
std::cout << "|C| | | |\n" << endl;
while (win_lose(point_now, step_count) == 0)
{
string location;
unsigned location_letter = 0; // A/B/C
unsigned location_number = 0; // 1/2/3
begin: // a label
std::cout << "Player " << player << ", make your move: ";
cin >> location; // input the location (e.g. B2)
std::cout << endl;
switch (location[0])
{
case 'a': case 'A':
location_letter = 0;
break;
case 'b': case 'B':
location_letter = 1;
break;
case 'c': case 'C':
location_letter = 2;
break;
default: // illegal input
location_letter = 100; // indicate an error
break;
}
switch (location[1])
{
case '1':
location_number = 0;
break;
case '2':
location_number = 1;
break;
case '3':
location_number = 2;
break;
default: // illegal input
location_number = 100; // indicate an error
break;
}
try
{
if (location_letter != 100 && location_number != 100 && point_now[location_letter][location_number] == ' ')
point_now[location_letter][location_number] = player;
else throw runtime_error("Illegal input!");
}
catch(runtime_error err)
{
std::cout << err.what() << "\nTry Again? Rnter Y or N." << endl;
char decision;
cin >> decision;
if (!cin || decision == 'n' || decision == 'N')
break;
else
{
cout << endl;
goto begin; // go back to the label 'begin'
}
}
// Print the board
std::cout << "| |1|2|3|" << endl;
std::cout << "|A|" << point_now[0][0] << "|" << point_now[0][1] << "|" << point_now[0][2] << "|" << endl;
std::cout << "|B|" << point_now[1][0] << "|" << point_now[1][1] << "|" << point_now[1][2] << "|" << endl;
std::cout << "|C|" << point_now[2][0] << "|" << point_now[2][1] << "|" << point_now[2][2] << "|" << endl;
game_player_change(player); // change the player
++step_count; // count one more time
std::cout << endl;
}
int final_result = win_lose(point_now, step_count);
switch (final_result)
{
case 1:
std::cout << "Congratulations! The winner is X." << endl;
break;
case 2:
std::cout << "Congratulations! The winner is 0." << endl;
break;
case 3:
std::cout << "The game ended in a draw." << endl;
break;
}
std::cout << "\nALL RIGHTS RESERVED (c) 2020 Teddy van Jerry" << endl;
return 0;
}
//Copyright :2020 Teddy van Jerry
输出示例
分析
- 该程序的优点:
97-115行对于不合法输入进行了判别(分为两种:1.坐标超出范围,2.输入到原来已有棋子的位置上) - 编写该程序的思路:
首先写main,如果遇到复杂的内容,另建函数,比如此处的判断输赢和交换选手。
调试过程比较顺利,发现了几个问题。1.棋盘输出位置不对,调整输出棋盘的代码即可。 2.有一种胜利情况没有判别出来,检查发现18,19,20,27,28,29行有坐标写错了(要细致啊!!!)。 - 感想
能自己写出来这样的程序,真的很有成就感的!!!
ALL RIGHTS RESERVED © 2020 Teddy van Jerry
欢迎转载,转载请注明出处。
See also
Teddy van Jerry 的导航页
【C++ 程序】 井字棋游戏(人 VS Lv1电脑)
【C++ 程序】 井字棋游戏(人 VS Lv2电脑)
【C++ 程序】 井字棋游戏(人 VS Lv3电脑)
【C++ 程序】 井字棋游戏(人 VS Lv3电脑)(战绩统计版)
【C++ 程序】 五子棋游戏(人 VS 人)
【C++ 程序】 随机数
【C++ 程序】 移动迷宫游戏
【C++ 程序】 贪吃蛇游戏
【C++ 程序】 数字推盘游戏(15-puzzle)
【C++ 程序】 2048游戏
【C++ 程序】 井字棋游戏(人 VS 人)(EasyX 图形界面)
【C++ 程序】 井字棋游戏(人 VS Lv3电脑)(战绩统计版)(EasyX 图形界面)
【C++ 程序】 2048游戏(EasyX 图形界面)
【C++ 程序】 贪吃蛇游戏(EasyX 图形界面)