当前位置: 首页 > news >正文

三子棋小游戏

使用C语言编写代码,实现一个简单小游戏---三子棋

这里创建1个game.h文件,用来声明函数、宏的文件,一个game.c文件用来实现函数game(),一个play.h文件用来作为该游戏的源文件。

具体代码如下:

1.game.h文件

#pragma once#include<stdio.h>
#include<stdlib.h>
#include<time.h>#define ROW 3
#define COL 3  //这是一个宏定义。宏定义用于在程序中指定一个常量或表达式的标识符,
/*并且在编译时将其替换为指定的值。在这个例子中,它定义了一个常量ROW和COL。
在程序中,可以使用ROW来代替数字3,使得程序更易于理解和维护*///初始化棋盘
void InitBoard(char borad[ROW][COL], int row, int col);//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);//判断输赢:
//玩家赢---*
//电脑赢---#
//平局---Q
//继续---Cchar IsWin(char board[ROW][COL], int row, int col);

2.game.c文件

#include"game.h"void InitBoard(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;for (i = 0;i < row;i++){for (j = 0;j < col;j++){board[i][j] = ' ';}}
}void DisplayBoard(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0;i < row;i++){int j = 0;for (j = 0;j < col;j++){printf(" %c ", board[i][j]);if (j < col - 1){printf("|");}}printf("\n");if (i < row - 1){int j = 0;for (j = 0;j < col;j++){printf("---");if (j < col - 1){printf("|");}}printf("\n");}}
}void PlayerMove(char board[ROW][COL], int row, int col)
{int x = 0;int y = 0;printf("玩家请下棋->\n");while (1){printf("请输入坐标->:");scanf_s("%d %d", &x, &y);//坐标范围合法的判断if (x >= 1 && x <= row && y >= 1 && y <= col){if (board[x - 1][y - 1] == ' ')//x,y减1,是因为这里代表行和列,例如有3行,那么x的取值范围为1-3,但是数组下标为0-2,所以要减去1{board[x - 1][y - 1] = '*';break;}else{printf("坐标被占用,不能下棋,请选择其他位置\n");}}else{printf("坐标非法,请重新输入\n");}}
}void ComputerMove(char board[ROW][COL], int row, int col)
{printf("电脑下棋->\n");int x = 0;int y = 0;while (1){x = rand() % row;//注意这里x的是取余数,所以范围是0到row-1,与上面的取值范围不同y = rand() % col;if (board[x][y] == ' '){board[x][y] = '#';break;}}
}//判断棋盘是否满了
//满了---返回1
//不满---返回0
IsFull(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;for (i = 0;i < row;i++){for (j = 0;j < col;j++){if (board[i][j] == ' '){return 0;}}}return 1;
}char IsWin(char board[ROW][COL], int row, int col)
{//行int i = 0;for (i = 0;i < row;i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' '){return board[i][1];}}//列int j = 0;for (j = 0;j < row;j++){if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' '){return board[1][j];}}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];}//没有人赢,平局,返回Qif (IsFull(board, row, col)){return 'Q';}//继续return 'C';
}

下面是部分函数解释:

game.h文件中包括了初始化棋盘、打印棋盘、玩家下棋、电脑下棋、判断棋盘是否满了、判断输赢等函数的实现。

1. InitBoard()函数用于初始化棋盘。遍历二维数组board,将每个元素初始化为空格。

2. DisplayBoard()函数用于打印棋盘。通过循环遍历二维数组board,在每个位置输出当前棋盘上的棋子,并在棋子之间输出分隔线。

3. PlayerMove()函数用于玩家下棋。通过提示玩家输入坐标,然后判断坐标的合法性。合法的坐标范围为1到行数和列数,若坐标合法并且对应位置为空,则将该位置标记为玩家的棋子。

4. ComputerMove()函数用于电脑下棋。通过随机生成坐标,然后判断坐标对应位置是否为空,若为空,则将该位置标记为电脑的棋子。

5. IsFull()函数用于判断棋盘是否满了。遍历棋盘上的每个位置,若存在空格,则返回0表示棋盘未满,否则返回1表示棋盘已满。

6. IsWin()函数用于判断是否有人获胜。首先检查每行是否有连续相同的棋子,然后检查每列是否有连续相同的棋子,最后检查对角线是否有连续相同的棋子。若存在连续相同的棋子,则返回对应的棋子标记。若棋盘已满但没有人获胜,则返回Q表示平局。若棋盘未满且没有人获胜,则返回C表示继续。

 3.play.c文件

#include"game.h"
#include<stdio.h>void menu()
{printf("**************************\n");printf("***** 1.play  0.exit *****\n");printf("**************************\n");
}void game()
{char ret = 0;char board[ROW][COL] = { 0 };InitBoard(board, ROW,COL);//初始化棋盘DisplayBoard(board, ROW, COL);//打印棋盘while (1){PlayerMove(board, ROW, COL);//判断输赢ret=IsWin(board, ROW, COL);if (ret != 'C'){break;}DisplayBoard(board, ROW, COL);ComputerMove(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{printf("平局\n");}DisplayBoard(board, ROW, COL);
}int main()
{srand((unsigned int)time(NULL));//设置随机数的生成起点int input = 0;do{menu();printf("是否开始游戏->:");scanf_s("%d", &input);switch(input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("输入错误,请重新输入->:\n");break;}} while (input);return 0;
}

运行结果如下: 

相关文章:

  • 【React】组件通信
  • Android 已经过时的方法用什么新方法替代?
  • 使用Python解决数据分析中的相关性分析
  • macOS 15 Blank OVF - macOS Sequoia 虚拟化解决方案
  • 分享个锂电池升压芯片,3.7V升5V大电流输出的芯片。AD2403 PWM升压芯片
  • 如何创建一个包含多个列的表?
  • 828华为云征文|华为云Flexus云服务器X实例——部署EduSoho网校系统、二次开发对接华为云视频点播实现CDN加速播放
  • fastadmin本地安装插件提示”请从官网渠道下载插件压缩包(code:2)(code:1)“
  • 数据结构(Day18)
  • vue-pdf 实现pdf预览、高亮、分页、定位功能
  • 问题记录:end value has mixed support, consider using flex-end instead
  • docker和ufw冲突问题
  • SpringBoot开发——整合P6Spy详细记录SQL执行耗时情况
  • 智能识别猫猫
  • Day 1 词汇备战
  • 【css3】浏览器内核及其兼容性
  • Cookie 在前端中的实践
  • ES学习笔记(12)--Symbol
  • Javascript基础之Array数组API
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • Puppeteer:浏览器控制器
  • Redis字符串类型内部编码剖析
  • vue2.0项目引入element-ui
  • 创建一种深思熟虑的文化
  • - 概述 - 《设计模式(极简c++版)》
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 什么是Javascript函数节流?
  • 消息队列系列二(IOT中消息队列的应用)
  • 转载:[译] 内容加速黑科技趣谈
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (02)Hive SQL编译成MapReduce任务的过程
  • (10)ATF MMU转换表
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (C++17) optional的使用
  • (PySpark)RDD实验实战——取一个数组的中间值
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (十六)Flask之蓝图
  • (四)stm32之通信协议
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • (一)SpringBoot3---尚硅谷总结
  • (转)ORM
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET运行机制
  • @Value获取值和@ConfigurationProperties获取值用法及比较(springboot)
  • []利用定点式具实现:文件读取,完成不同进制之间的
  • [2016.7 Day.4] T1 游戏 [正解:二分图 偏解:奇葩贪心+模拟?(不知如何称呼不过居然比std还快)]
  • [5] CUDA线程调用与存储器架构
  • [BJDCTF2020]The mystery of ip1
  • [C#]winform利用seetaface6实现C#人脸检测活体检测口罩检测年龄预测性别判断眼睛状态检测