C语言实现简单的控制台三子棋游戏

 更新时间:2020年11月06日 08:54:25   作者:一入猿门深似海  
这篇文章主要为大家详细介绍了C语言实现简单的控制台三子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

用C语言实现简单的控制台三子棋游戏

首先,确定一局游戏的基本流程:

1、创建棋盘并初始化。(将棋盘看作一个二维数组)
2、打印显示出棋盘。
3、玩家落子(玩家通过输入行列坐标的方式来落子)。
4、判定胜负关系。(如果玩家胜出,则退出游戏。)
5、电脑落子(随机位置落子) 。
6、判定胜负关系(如果电脑胜出,退出游戏。否则,回到步骤 2 继续执行。)

第一步,此处通过构造menu()函数搭建一个简单的交互菜单和玩家交互,用来判断是否开始进行一局游戏。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int menu() {
 printf("====================\n");
 printf("1.开始游戏\n");
 printf("0.结束游戏\n");
 printf("====================\n");
 printf(" 请输入您的选择: ");
 int choice = 0;
 scanf("%d", &choice);
 return choice;
}
int main() {
 while (1) {
 int choice = menu();
 if (choice == 1) {
 //game();//此处调用了一个game函数。
 }
 else if (choice == 0) {
 printf("goodbye!\n");
 break;
 }
 }
 system("pause");
 return 0;
}

第二步,对第一步中调用的game()函数进行构造。game()函数为核心功能函数,其主要任务是完成基本流程。

1.构建初始化init()函数。初始化一个3*3的二维数组,将它当做棋盘,并将数组元素全部初始化为0。

void init(char chessBoard[MAX_ROW][MAX_COL]) {
 // 把数组中的每个元素都设=初始化为“空格”。
 for (int row = 0; row < MAX_ROW; row++) {
 for (int col = 0; col < MAX_COL; col++) {
 chessBoard[row][col] = ' ';
 }
 }
}

2.构建棋盘打印printChessBoard()函数。运用for循环打印出3*3的棋盘。

void printChessBoard(char chessBoard[MAX_ROW][MAX_COL]) {
 //把棋盘打印出来。
 printf("+---+---+---+\n");
 for (int row = 0; row < MAX_ROW; row++) {
 printf("| %c | %c | %c |\n", chessBoard[row][0],
 chessBoard[row][1], chessBoard[row][2]);
 printf("+---+---+---+\n");
 }
}

3.构建玩家落子playerMove()函数,玩家通过输入行列坐标的方式来落子。此过程中需要判断:1.玩家输入的行列坐标是否在棋盘的合理位置。2.玩家输入的行列坐标位置是否已经有棋子。

void playerMove(char chessBoard[MAX_ROW][MAX_COL]) {
 // 让玩家落子. 通过控制台输入行列坐标的方式来实现。
 while (1) {
 printf(" 请玩家输入坐标(row col): ");
 int row = 0;
 int col = 0;
 scanf("%d %d", &row, &col);
 // 校验玩家输入的坐标是否合法(是否在棋盘合理范围内)。
 if (row < 0 || row >= MAX_ROW
 || col < 0 || col >= MAX_COL) {
 // 若出现非法情况,此时应该让玩家重新输入。
 printf("您的坐标不在合法范围[0, 2]内 \n");
 continue;
 }
 // 校验玩家落子位置是否已经有子了。 
 if (chessBoard[row][col] != ' ') {
 printf("您的坐标位置已经有子了!\n");
 continue;
 }
 // 真正落子。用“X”表示玩家落子。
 chessBoard[row][col] = 'x';
 break;
 }
}

4.构建一个computerMove()函数来控制电脑落子。通过电脑产生一系列随机数来控制棋子落在棋盘坐标范围内。

void computerMove(char chessBoard[MAX_ROW][MAX_COL]) {
 // 电脑落子,让电脑随机产生一组行列坐标。
 while (1) {
 int row = rand() % MAX_ROW;
 int col = rand() % MAX_COL;
 if (chessBoard[row][col] != ' ') {
 // 需要保证随机数不能是已经有棋子的位置。
 continue;
 }
 chessBoard[row][col] = 'o';
 break;
 }
}

在该函数模块中,电脑落子随机位置的生成通过rand()函数控制,需要注意的是,我们需要通过设置随机种子来避免“伪随机”的出现。

srand((unsigned int)time(0));//以当前时间戳作为随机种子。

5.构建isWin()函数判断是否胜利。此处人为约定该函数的返回结果的含义: ‘x' 表示玩家获胜。‘o' 表示电脑获胜。 ' ' 表示胜负未分。 ‘q' 表示和棋。

char isWin(char chessBoard[MAX_ROW][MAX_COL]) {
 // 判定所有的行。
 for (int row = 0; row < MAX_ROW; row++) {
 if (chessBoard[row][0] != ' '
 && chessBoard[row][0] == chessBoard[row][1]
 && chessBoard[row][0] == chessBoard[row][2]) {
 return chessBoard[row][0];
 }
 }
 // 判定所有的列。
 for (int col = 0; col < MAX_COL; col++) {
 if (chessBoard[0][col] != ' '
 && chessBoard[0][col] == chessBoard[1][col]
 && chessBoard[0][col] == chessBoard[2][col]) {
 return chessBoard[0][col];
 }
 }
 // 判定两个对角线。
 if (chessBoard[0][0] != ' '
 && chessBoard[0][0] == chessBoard[1][1]
 && chessBoard[0][0] == chessBoard[2][2]) {
 return chessBoard[0][0];
 }
 if (chessBoard[2][0] != ' '
 && chessBoard[2][0] == chessBoard[1][1]
 && chessBoard[2][0] == chessBoard[0][2]) {
 return chessBoard[2][0];
 }
 // 判定是否和棋。看棋盘中是否有剩余空间。
 //调用了isFull函数。
 if (isFull(chessBoard)) {
 return 'q';
 }
 return ' ';
}

6.构造isFull()函数用来判断棋盘中是否有剩余空间供玩家落子,以便判断是否是和棋。

int isFull(char chessBoard[MAX_ROW][MAX_COL]) {
 // 找”空格“. 如果找不到, 说明棋盘满了。
 for (int row = 0; row < MAX_ROW; row++) {
 for (int col = 0; col < MAX_COL; col++) {
 if (chessBoard[row][col] == ' ') {
 // 如果找到“空格”说明棋盘没满。
 return 0;
 }
 }
 }
 return 1;
}

最后,根据组合调用上面的几个功能函数,我们可以获得最终的game()函数的整体架构。

void game() {
 // 1. 创建棋盘并初始化
 char chessBoard[MAX_ROW][MAX_COL] = { 0 };
 init(chessBoard);//调用初始化函数
 char winner = ' ';
 while (1) {
 // 2. 打印棋盘
 printChessBoard(chessBoard);
 // 3. 玩家落子(玩家输入行列坐标的方式来落子)
 playerMove(chessBoard);
 // 4. 判定胜负关系
 winner = isWin(chessBoard);
 if (winner != ' ') {
 break;
 }
 // 5. 电脑落子(随机位置落子) 
 computerMove(chessBoard);
 // 6. 判定胜负关系
 winner = isWin(chessBoard);
 if (winner != ' ') {
 break;
 }
 }
 printChessBoard(chessBoard);
 if (winner == 'x') {
 printf("恭喜您, 您赢了!\n");
 }
 else if (winner == 'o') {
 printf("很遗憾, 您输了!再接再厉!\n");
 }
 else {
 printf("您棋逢对手,这一局是平局!\n");
 }
}

运行截图如下:

胜利啦!

失败了!

此处有棋子!

更多有趣的经典小游戏实现专题,分享给大家:

C++经典小游戏汇总

python经典小游戏汇总

python俄罗斯方块游戏集合

JavaScript经典游戏 玩不停

java经典小游戏汇总

javascript经典小游戏汇总

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • C++多线程实现TCP服务器端同时和多个客户端通信

    C++多线程实现TCP服务器端同时和多个客户端通信

    通讯建立后首先由服务器端发送消息,客户端接收消息;接着客户端发送消息,服务器端接收消息,实现交互发送消息。本文主要介绍了C++多线程实现TCP服务器端同时和多个客户端通信,感兴趣的可以了解一下
    2021-05-05
  • 详解C++11中模板的优化问题

    详解C++11中模板的优化问题

    这篇文章主要介绍了C++11中模板的优化问题,通过实例代码得出结论,当所有模板参数都有默认参数时,函数模板的调用如同一个普通函数,具体示例代码跟随小编一起看看吧
    2021-09-09
  • 浅谈C++ Socket编程

    浅谈C++ Socket编程

    本文给大家简单介绍了C++中的Socket编程的种类以及sockets编程的8个步奏,简单生动,有需要的小伙伴可以参考下
    2017-07-07
  • C++继承介绍

    C++继承介绍

    C++继承可以是单一继承或多重继承,每一个继承连接可以是public,protected,private也可以是virtual或non-virtual
    2013-01-01
  • C++实现bmp格式图像读写

    C++实现bmp格式图像读写

    这篇文章主要为大家详细介绍了C++实现bmp格式图像读写,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • C++中关于Crt的内存泄漏检测的分析介绍

    C++中关于Crt的内存泄漏检测的分析介绍

    本篇文章介绍了,在C++中关于Crt的内存泄漏检测的分析说明。需要的朋友参考下
    2013-04-04
  • C语言实现bmp图像对比度扩展

    C语言实现bmp图像对比度扩展

    这篇文章主要为大家详细介绍了C语言实现bmp图像对比度扩展,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • C语言中获取和改变目录的相关函数总结

    C语言中获取和改变目录的相关函数总结

    这篇文章主要介绍了C语言中获取和改变目录的相关函数总结,包括getcwd()函数和chdir()函数以及chroot()函数的使用方法,需要的朋友可以参考下
    2015-09-09
  • c++中#include &lt;&gt;与#include""的区别详细解析

    c++中#include &lt;&gt;与#include""的区别详细解析

    <>先去系统目录中找头文件,如果没有在到当前目录下找。所以像标准的头文件 stdio.h、stdlib.h等用这个方法
    2013-10-10
  • typedef和#define的用法以及区别

    typedef和#define的用法以及区别

    以下是对C/C++语言中,typedef和#define的用法以及区别进行了详细的介绍,需要的朋友可以过来参考下
    2013-10-10

最新评论