前情提要:这是一个让电脑赢比自己赢更难的游戏(请看电脑回合解释)
1、初始化棋盘:首先使用一个二位数组建立棋盘信息存储玩家和电脑下的棋子信息,玩家执'*'棋子,电脑执'#'棋子 ,可随意更换你所想的字符表示;一开始二维数组初始化为空格,在控制台打印出还没有下棋的状态。
2、打印棋盘:把二位数组遍历一遍,注意左右空格,以及边界的横线竖线,在控制台上打印出较为工整的棋盘。
3、玩家下棋:提示玩家输入坐标,注意判断坐标是否在棋盘的范围内,在范围内,再判断该坐标是否被占用,占用则继续提示重新输入。
4、电脑回合:使用C语言rand函数配合srand随机数发生器和时间戳函数生成随机数,使电脑在棋盘的随机下棋,生成坐标判断是否被占用,未占用下棋标记。(程序的随机都是算法伪随机,就像各电子竞技的匹配机制,著名的ELO机制)
5、棋盘是否已满:只要棋盘上还有位置未被占用,棋盘就未满。
6、输赢判断:判断行,列,正斜线,反斜线上的棋子是否都为玩家或者电脑的棋子,来判断输赢,再判断是否棋盘已满,满了平局,未满游戏继续。
这就是简单三子棋的设计思路,详见下列代码,代码有详细注释:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3 //行
#define COL 3 //列
//玩家执'*'棋子
//电脑执'#'棋子
//初始化棋盘
void BoardInit(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家回合
void PlayMove(char board[ROW][COL], int row, int col);
//电脑回合
void ComMove(char board[ROW][COL], int row, int col);
//判断平局
int IsFull(char board[ROW][COL], int row, int col);
//判断胜负
char IsWin(char board[ROW][COL], int row, int col);
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//把棋盘都初始化为空格
void BoardInit(char board[ROW][COL], int row, int col)
{
//行
for (int i = 0; i < row; i++)
{
//列
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';//依次初始化为空格
}
}
}
//打印显示棋盘信息
void DisplayBoard(char board[ROW][COL], int row, int col)
{
//行
for (int i = 0; i < row; i++)
{
//列
for (int j = 0; j < col; j++)
{
//依次显示棋盘上的字符
printf(" %c ", board[i][j]);
//中间隔开 最后一列边界不需要隔开
if (j < col - 1)
printf("|");
}
//换行显示行与行之间的分界线
printf("\n");
//三行只需要两条分界线
if (i < row - 1)
{
for (int j = 0; j < col; j++)
{
//显示分界线
printf("---");
//同一行也分开,显示一个一个格子
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
//玩家回合
void PlayMove(char board[ROW][COL], int row, int col)
{
//玩家输入的x,y坐标
int x = 0, y = 0;
//提示玩家下棋
printf("玩家出棋:>\n");
while (1)
{
scanf("%d %d", &x, &y);
//先判断坐标是否在棋盘内,不在直接重新输入
if (x >= 1 && x <= row + 1 && y >= 1 && y <= col)
{
//再判断坐标是否已经有棋子,有棋子直接重新输入
if (board[x - 1][y - 1] != ' ')
printf("坐标被占用,请重新输入\n");
else
{
//没有被占用,就可以把棋子下下去
board[x - 1][y - 1] = '*';
break;
}
}
//提示玩家重新输入
else
printf("坐标输入错误,请重新输入\n");
}
}
//电脑回合
void ComMove(char board[ROW][COL], int row, int col)
{
//显示电脑下棋
printf("电脑出棋\n");
while (1)
{
//电脑获取随机坐标,确保在棋盘内
int x = rand() % 3;
int y = rand() % 3;
//再判断随机坐标上是否已经下棋
//如果是循环重新获取,电脑不需要显示过程,直接获取到下棋为止
if (board[x][y] == ' ')
{
//没有被占用,就可以把棋子下下去
board[x][y] = '#';
break;
}
}
}
//判断平局
int IsFull(char board[ROW][COL], int row, int col)
{
//依次判断所有坐标是否有棋子
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
//只要有一个位置是空的,游戏就继续,返回0
if (board[i][j] == ' ')
return 0;
}
}
//如果棋盘已满,返回1
return 1;
}
//判断胜负
char IsWin(char board[ROW][COL], int row, int col)
{
//行判断,依次判断每一行的棋子是否相同,如果相同,返回棋盘上的字符即可判断输赢
for (int i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
//列判断,依次判断每一列的棋子是否相同,如果相同,返回棋盘上的字符即可判断输赢
for (int 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[0][0] != ' ')
return board[0][0];
//反斜线,判断反斜线的棋子是否相同,如果相同,返回棋盘上的字符即可判断输赢
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
return board[0][2];
//每个回合,判断棋盘是否已满
//满了返回字符'D'结束游戏
//未满返回字符'C'继续游戏
int ret = IsFull(board, row, col);
if (ret == 1)
return 'D';//平局
else
return 'C';//继续
}
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//菜单
void menu()
{
printf("***********************\n");
printf("******* 1,play ********\n");
printf("******* 0.exit ********\n");
printf("***********************\n");
}
//整个游戏过程
void game()
{
//ret 记录判断输赢继续结束
char ret = 0;
//建立棋盘
char board[ROW][COL] = { 0 };
//初始化棋盘
BoardInit(board, ROW, COL);
//显示棋盘
DisplayBoard(board, ROW, COL);
//开始游戏
//玩家执'*'棋子
//电脑执'#'棋子
while (1)
{
//玩家下棋
PlayMove(board, ROW, COL);
//判断结果
ret = IsWin(board, ROW, COL);
//如果不是继续,就结束
if (ret != 'C')
break;
//继续,显示棋盘
DisplayBoard(board, ROW, COL);
//电脑下棋
ComMove(board, ROW, COL);
//判断结果
ret = IsWin(board, ROW, COL);
//如果不是继续,就结束
if (ret != 'C')
break;
//继续,显示棋盘,继续循环
DisplayBoard(board, ROW, COL);
}
//棋盘已满平局,或者输赢判断
if (ret == '*')//玩家胜利
printf("玩家胜利\n");
else if (ret == '#')//电脑胜利
printf("电脑胜利\n");
else if (ret == 'D')//平手
printf("双方握手言合\n");
//显示最终棋局
printf("最终棋盘的棋子如下:\n");
DisplayBoard(board, ROW, COL);
}
void test()
{
//配置随机数发生器,和rand配合使用
srand((unsigned int)time(NULL));
int input = 0;
//加载菜单,玩家选择玩游戏,退出游戏
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
//玩家执'*'棋子
//电脑执'#'棋子
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}