三子棋是一个大家都很熟悉的游戏,思路非常简单,用O代表电脑,X代表玩家。在程序员的眼里三子棋的实现和数组、函数等内容有着密不可分的关联。三子棋的棋盘我们都见过,坐标成对出现,二维数组就可以完美的解决。这里模块化的解决思想就凸显的十分重要,将要解决的问题封装成一个个函数,那我们具体分析三子棋具体要解决哪些问题?
首先得提供给用户菜单供选择,接下来得打印出它的棋盘界面,玩的过程电脑走一步人走一步,游戏具体怎样实现以及判断每一步接下来什么情况该继续走,大致分为六大部分。下面将分析每一部分以及它的具体实现。
1、头文件:使函数调用方便,程序更加整齐
#define _CRT_SECURE_NO_WARNINGS 1
#ifndef _THREE_CHESS_H_
#define _THREE_CHESS_H_
#include <stdio.h>
#include <windows.h>
#include <time.h>
#pragma warning(disable:4996)
#define ROW 3
#define COL 3
void ShowUI(); //以下是函数声明
void Game();
void ComputerMove(char board[][COL], int row, int col);
void ShowBoard(char board[][COL], int row, int col);
char Judge(char board[][COL], int row, int col);
void PlayerMove(char board[][COL], int row, int col);
#endif
2、显示菜单函数:
这个函数非常简单,printf语句也十分明了。附录如下
void ShowUI()
{
printf("##################################\n");
printf("## 1. Play 2. Exit ##\n");
printf("##################################\n");
printf("Please Select:> ");
}
3、棋盘显示函数:(供game函数调用)
三子棋棋盘是一个九宫格(三行三列),首先打印列1、2、3,定义两个变量i和j分别控制行和列,只要i小于row,则打印i+1,循环条件为i<row,(row和col在都宏定义为3),就会打印出来行1、2、3.内层嵌套循环打印 | ,输出board[i][j],这样一个简单九宫格就打印出来了。
void ShowBoard(char board[][COL], int row, int col)
{
printf(" 1 2 3\n");
printf("-----------------\n");
int i = 0;
int j = 0;
for (; i < row; i++)
{
printf("%d |", i + 1);
for (j = 0; j < col; j++)
{
printf(" %c |", board[i][j]);
}
printf("\n-----------------\n");
}
printf("\n");
}
4、电脑下棋函数:(供game函数调用)
因为电脑是自动落子,所以得为电脑产生一个随机的 棋子二维数组下标值,使电脑随机落子,这个用srand((unsigned)time(NULL));(在game函数中将具体实现),此函数只需要随机生成行和列,让棋盘坐标去判断是不是等于空,如果等于空则用O填充,循环条件为真,因为每一步都要去随机生成行和列。
void ComputerMove(char board[][COL], int row, int col)
{
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = 'O';
break;
}
}
}
5、用户下棋函数:(供game函数调用)
首先得从键盘输入坐标,判断输入的坐标是否合法,行和列都在3以内,则判定输入合法,如果用户输入的位置为空,则可以用X填充,否则重新输入。
void PlayerMove(char board[][COL], int row, int col)
{
int x, y;
while (1)
{
printf("Please Enter Your Pos(x,y):> ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = 'X';
break;
}
else
{
printf("Enter Pos Is Not OK, Try Again!\n");
}
}
else
{
printf("Enter Error, Try Again!\n");
}
}
}
6、具体玩游戏部分
先把棋盘初始化为空格,在这里不断去调用其它子函数,每调一次判断一次结果,共有四种可能,用switch语句实现,(电脑赢、玩家赢、平局、其它),如果有结果就break跳出,没有结果则继续进行游戏。
注释:memset是计算机中C/C++语言初始化函数。作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。
void Game()
{
char board[ROW][COL];
memset(board, ' ', sizeof(board)); //用空格去初始化
char result = 'N';
srand((unsigned long)time(NULL)); //使电脑随机落子
while (1)
{
system("cls"); //实现清屏
ComputerMove(board, ROW, COL);
ShowBoard(board, ROW, COL);
result = Judge(board, ROW, COL);
if (result != 'N')
{
break;
}
PlayerMove(board, ROW, COL);
ShowBoard(board, ROW, COL);
result = Judge(board, ROW, COL);
if (result != 'N')
{
break;
}
}
switch (result) //'X' 'O' 'E' 'N'作为switch语句的选择项
{
case 'X':
printf("You Win! :)\n");
break;
case 'O':
printf("You Lose, Computer Win! :(\n");
break;
case 'E':
printf("平局,恭喜!\n");
break;
default:
break;
}
}
7、判断函数Judge:
游戏要想继续,每走一步就要显示一个结果。要非常清楚三子棋赢得条件是什么,要么连续三行或三列一样,要么对角线元素一样,并且不能等于空。这就是判断函数要实现的功能。
char Judge(char board[][COL], int row, int col)
{
int i = 0;
int j = 0;
for (; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && \
board[i][0] != ' ') //判断行
{
return board[i][0];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && \
board[0][i] != ' ') //判断列
{
return board[0][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] &&\
board[1][1] != ' ') //判断对角线
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] &&\
board[1][1] != ' ') //判断反对角线
{
return board[1][1];
}
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 'N'; //返回结果
}
}
}
return 'E'; //判断完,满了并且没成说明平局
}
8、主函数main():
负责将其他函数串起来,使得思路非常清晰switch语句分三种情况,1和2执行菜单,其他的数字说明输入错误。
int main()
{
int select = 0;
int quit = 0;
while (!quit)
{
ShowUI();
scanf("%d", &select);
switch (select)
{
case 1:
Game();
break;
case 2:
quit = 1;
printf("Bye,Bye!\n");
break;
default:
printf("Please Enter Again!\n");
break;
}
}
system("pause");
return 0;
}
运行结果示例:
棋盘界面
平局
你输了
你赢了