【C语言学习笔记】:三子棋具体步骤和代码

news2024/12/24 8:47:41

一、问题描述

用c语言实现三子棋。

二、基本流程

在写三子棋的代码之前,我们来看看实现这个游戏的逻辑:

1.菜单界面选择开始或者退出游戏。2.创建棋盘并初始化。3.打印棋盘。4.玩家落子(玩家输入行列坐标的方式来落子),'x’表示玩家落子。5.判定胜负关系(输,赢,和棋),'q’表示和棋。6.电脑落子(随机位置落子) ,'o’表示电脑落子。7.判定胜负关系。8.回到 步骤2 继续执行。

三、步骤

1.菜单界面

1.开始游戏 0.退出游戏

int menu(){
printf("--------------------------\n");
printf("--------1.开始游戏--------\n");
printf("--------0.退出游戏--------\n");
printf("--------------------------\n");
int choice = 0;
printf("请输入你的选择:");
scanf("%d", &choice);
return choice;
}

2.创建棋盘

棋盘:使用3行3列的二维数组来表示,元素类型是char。

使用宏定义的原因:1.推高代码可读性,后续代码中遇到3,方便理解含义。2.提高扩展性,如果将来要修改棋盘尺寸,代码修改会很方便。

#define MAX_ROW 3
#define MAX_COL 3
char chessBoard[MAX_ROW][MAX_COL] = { 0 };

3.棋盘初始化

’ '表示棋盘上的空白区域

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] = ' ';
}
}
}

4.打印棋盘

(1)简陋方法:

void print_chessBoard(char chessBoard[MAX_ROW][MAX_COL]){
for (int row = 0; row <MAX_ROW; row++){
for (int col = 0; col < MAX_COL; col++){
printf("%c",chessBoard[row][col]) ;
}
printf("\n");
}

}
123456789

结果:

注意:这里不是棋盘没打印出来,而是我们使用’ '表示空白区域,所以我们看到的棋盘是一片黑色。这样看的不是很清楚,所以我们选用更加美观的方法打印。

(2)美观方法:

void print_chessBoard(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");
}
}
12345678

结果:

5.玩家落子

玩家输入行列坐标表示落子,使用’x’表示玩家落子。

注意:1.玩家落子需要在棋盘范围内。2.玩家要在棋盘上空的地方落子。3.如果输入的坐标不满足要重新输入。

void playerMove(char chessBoard[MAX_ROW][MAX_COL]){
while (1){
int row = 0;
int col = 0;
printf("请输入坐标(row col):");
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;
}
chessBoard[row][col] = 'x';
break;
}
}
123456789101112131415161718

6.电脑落子

电脑随机产生行列坐标,'o’表示电脑落子。

注意:1.要在主函数中使用srand((unsigned int)time(0))将时间作为随机数种子,确保得到的行列坐标是真随机。2.要在棋盘上空的地方下棋。

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;
}
}
1234567891011

7.判断胜负

此处约定返回结果的含义:(1)‘x’ 表示玩家获胜(2)‘o’ 表示电脑获胜(3)’ ’ 表示胜负未分(4) ‘q’ 表示和棋

1.判定是否和棋(1)调用isFull函数。(2)如果数组中有元素为’ ‘,那么没满,返回0。如果全不为’ ',满了,返回1。(3)如果棋盘满了未分出胜负,和棋。2.判定电脑玩家胜利(1)判定所有的行(2)判定所有的列(3)判定两条对角线

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;
}

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];
}
if (isFull(chessBoard)) {
return 'q';
}
return ' ';
}

四、结果演示

1.玩家胜利

2.电脑胜利

3.和棋

五、代码实现

#define _CRT_SECURE_NO_WARNINGS#define MAX_ROW 3#define MAX_COL 3#include <stdio.h>#include <stdlib.h>#include <time.h>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] = ' ';    }  }}void print_chessBoard(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");  }}void playerMove(char chessBoard[MAX_ROW][MAX_COL]){  while (1){    int row = 0;    int col = 0;    printf("请输入坐标(row col):");    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;    }    chessBoard[row][col] = 'x';    break;  }}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;  }}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;}//微信关注公众号【C语言中文社区】,免费领取200G精品学习资料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];  }  if (isFull(chessBoard)) {    return 'q';  }  return ' ';}void game(){  char chessBoard[MAX_ROW][MAX_COL] = { 0 };  init(chessBoard);  char winner = ' ';  while (1){    print_chessBoard(chessBoard);    playerMove(chessBoard);    winner = isWin(chessBoard);    if (winner != ' ') {      break;    }    computerMove(chessBoard);    winner = isWin(chessBoard);    if (winner != ' ') {      break;    }  }  print_chessBoard(chessBoard);  if (winner == 'x') {    printf("恭喜您, 您赢了!\n");  }  else if (winner == 'o') {    printf("哈哈,您连人工智障都下不过!\n");  }  else {    printf("您只能和人工智障打平手!!\n");  }}
int menu(){  printf("--------------------------\n");  printf("--------1.开始游戏--------\n");  printf("--------0.退出游戏--------\n");  printf("--------------------------\n");  int choice = 0;  printf("请输入你的选择:");  scanf("%d", &choice);  return choice;}int main(){  srand((unsigned int)time(0));  while (1){    int choice = menu();    if (choice == 1){      game();    }    else if (choice == 0){      printf("退出游戏,GOODBYE!!!!!\n");      break;    }    else{      printf("输入错误!请重新输入!\n");      continue;    }  }  system("pause");  return 0;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/390422.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

既然有MySQL了,为什么还要有Redis?

目录专栏导读一、同样是缓存&#xff0c;用map不行吗&#xff1f;二、Redis为什么是单线程的&#xff1f;三、Redis真的是单线程的吗&#xff1f;四、Redis优缺点1、优点2、缺点五、Redis常见业务场景六、Redis常见数据类型1、String2、List3、Hash4、Set5、Zset6、BitMap7、Bi…

ESP32学习笔记01-环境搭建

本文参考博客https://blog.csdn.net/weixin_43599390/article/details/123944479 1.下载离线版本的 ESP IDF esp idf 下载地址 2.安装 esp idf 2.1应用修复,后,再下一步 2.2 2.3 2.4 2.5

跨屏设计规范

跨屏设计规范 以windows10x 为例&#xff0c;其在具体交互上&#xff0c;到底有哪些常见的交互模式和硬件要如何结合 6.1跨平台的双屏交互设计逻辑 这种那个品的设计范式&#xff0c;其实是跨平台的通用规则&#xff0c; 在很大程度上&#xff0c;这套交互逻辑是不受操作系统…

【CSS】CSS 复合选择器 ③ ( 并集选择器 | 并集选择器与后代选择器示例 )

文章目录一、并集选择器1、语法说明2、代码示例二、并集选择器与后代选择器示例1、添加注释2、HTML 结构3、后代选择器 14、后代选择器 25、并集选择器6、完整代码示例7、显示效果一、并集选择器 1、语法说明 并集选择器 可以选择 若干 基础选择器 选择出的 并集元素集合 ; 并集…

【亲测】Centos7系统非管理(root)权限编译NCNN

前言 由于使用的是集群&#xff0c;自己不具有管理员权限&#xff0c;所以以下所有的情况均在非管理员权限下进行安装&#xff0c;即该安装策略仅适用于普通用户构建自己的环境。 什么是NCNN ncnn是一款非常高效易用的深度学习推理框架&#xff0c;支持各种神经网络模型&#x…

文件异步多备常用方案

业务需求上经常存在需要对同一个文件进行双上传&#xff0c;上传到不同云存储桶&#xff0c;以防出现某一个云厂商因各种意外导致自身服务出现不可用的情况&#xff0c;当然&#xff0c;还有其他措施可以避免&#xff0c;现在只针对通过程序业务代码而双写存储的这个场景。 业务…

Java分布式解决方案(三)

文章目录&#x1f525;MySQL事务-MySQL中锁的分类&#x1f525;MySQL事务-MySQL中的死锁问题&#x1f525;MySQL事务-MySQL中锁的分类 MySQL中锁的分类 从本质上讲&#xff0c;锁是一种协调多个进程或多个线程对某一资源的访问的机制&#xff0c;MySQL使用锁和MVCC机制实现了…

了解基本的html和javascript

用记事本编辑一个文本文件&#xff0c;代码如下&#xff0c; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>my name is bo</title> <script>alert(hello); </script> </head> <body>&…

实验2 设计模式实验1

实验内容: 1. 使用简单工厂模式设计一个可以创建不同几何形状(Shape)&#xff0c;例如圆形 (Circle)、矩形(Rectangle)和三角形(Triangle)等的绘图工具类&#xff0c;每个几何图形均具 有绘制方法draw()和擦除方法erase()&#xff0c;要求在绘制不支持的几何图形时&#xff…

Android 基础知识4-3.6 ToggleButton(开关按钮)Switch(开关)详解

一、ToggleButton(开关按钮) 1.1、简介 ToggleButton 类似开关有开和关两种状态&#xff0c;不同的状态下可以有不同的文本。 public class ToggleButton extends CompoundButton Displays checked/unchecked states as a button with a "light" indicator …

CNN基础

Tip&#xff1a;仅供自己学习记录&#xff0c;酌情参考 1. 前馈与反馈神经网络 神经网络有前馈神经网络和反馈神经网络&#xff0c;前向神经网络也就是前馈神经网络。 前馈型神经网络各神经元接收前一层的输入&#xff0c;并输出给下一层&#xff0c;没有反馈。节点分为两类…

nacos-sdk-rust binding to NodeJs

广告时间 nacos-sdk-rust-binding-node : nacos-sdk-rust binding to NodeJs with napi. Tip: nacos-sdk-nodejs 仓库暂未提供 2.x gRPC 交互模式&#xff0c;为了能升级它&#xff0c;故而通过 node addon 方式调用 nacos-sdk-rust npm 包 -> https://www.npmjs.com/packa…

Spring系列-8 AOP使用与原理

背景 按照软件重构的思想&#xff0c;当多个类中存在相同的代码时&#xff0c;需要提取公共部分来消除代码坏味道。Java的继承机制允许用户在纵向上通过提取公共方法或者公共部分(模版方法方式)至父类中以消除代码重复问题&#xff1b;日志、访问控制、性能监测等重复的非业务…

GO的IO接口和工具

GO的IO接口和工具 文章目录GO的IO接口和工具一、io包中接口的好处和优势1.1拷贝数据的函数二、 在io包中&#xff0c;io.Reader 的扩展接口和实现类型都有哪些2.1 io.Reader的扩展接口2.2 io.Reader接口的实现类型2.3 示例三、io包的接口&#xff0c;以及它们之间的关系3.1 读操…

Raki的读paper小记:Forget-free Continual Learning with Winning Subnetworks

Abstract&Introduction&Related Work 研究任务 用子网络做CL已有方法和相关工作 彩票假说&#xff08;LTH&#xff09;证明了稀疏子网络&#xff08;称为中奖彩票&#xff09;的存在&#xff0c;这些子网络保持了密集网络的性能&#xff0c;然而使用迭代修剪方法在持续…

Splunk 的一个Bug (Events from tracker.log have not been seen)

1:背景:Splunk version: 8.2.4 splunk 的一个alert: Events from tracker.log have not been seen for the last 47 seconds, which is more than the yellow threshold (45 seconds). This typically occurs when indexing or forwarding are falling behind or are blocked…

【15】linux命令每日分享——head命令查看文件

大家好&#xff0c;这里是sdust-vrlab&#xff0c;Linux是一种免费使用和自由传播的类UNIX操作系统&#xff0c;Linux的基本思想有两点&#xff1a;一切都是文件&#xff1b;每个文件都有确定的用途&#xff1b;linux涉及到IT行业的方方面面&#xff0c;在我们日常的学习中&…

德鲁特金属导电理论(Drude)

德鲁特模型的重要等式 首先我们建立德鲁特模型的重要等式 我们把原子对于电子的阻碍作用&#xff0c;用一个冲量近似表示出来 在式子 首先定义一个等效加速度 由于 我们可以得到电导率的微观表达式 在交流电环境中 电场的表达式 借鉴上一问的公式 我们可以列出这样的表达式…

1.5 全概率公式和贝叶斯公式

1.5.1 全概率公式在处理复杂事件的概率时&#xff0c;我们经常将这个复杂事件分解为若千个互不相容的较简单的事件之和&#xff0c;先求这些简单事件的概率&#xff0c;再利用有限可加性得到所求事件的概率,这种方法就是全概率公式的思想方法全概率公式是概率论中的一个非常重要…

【CSS】CSS 复合选择器 ② ( 子元素选择器 | 交集选择器 )

文章目录一、子元素选择器1、语法说明2、代码分析3、代码示例二、交集选择器1、语法说明2、代码示例一、子元素选择器 1、语法说明 子元素选择器 可以选择 某个基础选择器 选择出的 元素组 的 直接子元素 ( 亲儿子元素 ) 中 使用基础选择器 选择 元素 ; 子元素选择器语法 : 父选…