三子棋游戏小课堂

🪐🪐🪐欢迎来到程序员餐厅💫💫💫

今天的主菜是,C语言实现的三子棋小游戏,

              所属专栏:     C语言知识点   

              主厨的主页:Chef‘s blog


前言:

已经学会数组的朋友们注意啦,现在的你已经有能力写出两个小游戏了,一个是扫雷,一个是三子棋,今天咱们就来手搓三子棋代码。

涉及知识点:

  • 随机数的生成:C语言实现随机数
  • 数组的使用

1.游戏要求

1.此游戏为人机对战

2.一方的棋子连成一行或一列或对角线时胜利

3.默认是3*3的棋盘,但可修改

4.玩家可以通过菜单选择开始游戏或退出游戏

2.游戏分析

  • 1.电脑下的棋通过随机数生成
  • 2.我们应该用数组放置双方所下的棋子
  • 3.每时每刻其具有三种情况,即未分出胜负,一方获胜,平局。每次一方下完棋就该判断此时棋局的情况。
  • 4.设置菜单使玩家可以选择退出游戏或开始游戏

3.多文件操作

 为了方便代码的管理和保证游戏实现逻辑的清晰性,我们将采用多文件管理的模式。

        (1)创建头文件game.h,包含所有头文件(其他源文件只需引用它即可),以及所有游戏功能的函数接口。

        (2)创建源文件game.c,负责所有游戏功能对应函数的具体代码实现。

        (3)创建源文件main.c,负责调用函数实现来游戏。

4.  简易菜单的实现

4.1功能介绍

 1.玩家可以通过选择1进入游戏,0退出游戏。

2.选错的话提醒玩家,重新选择。

3.告诉玩家游戏规则

4.2功能实现

#define _CRT_SECURE_NO_WARNINGS 1
#include"源.h"
void menu()
{
	printf("*********************\n");
	printf("****开始   :1*******\n");
	printf("****结束   :0********\n");//打印菜单
	printf("*********************\n");
}
void rules()
{
	printf("游戏规则如下:\n");
	printf("1.此游戏为人机对战\n2.一方的棋子连成一行或一列或对角线时胜利\n3.横坐标是1—3,纵坐标是1—3\n4.输入1是开始游戏输入0是退出游戏\n");
}
int main()
{
	srand((unsigned int)time(NULL));//设置随机数种子
	int input = 0;
	do {
        rules();
        menu(); 
		printf("请选择:->");//玩家输入0表示退出游戏,输入1表示开始游戏
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始游玩三子棋,祝您好运!\n");
			game();//游戏内容的具体实现
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("请输入0 或 1 !\n");//防止有人捣乱,故意输错
			break;
		}
	} while (input);
	return 0;
}

4.3效果展示

5. 游戏功能实现

  5.1 要实现的函数接口

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define _CRT_SECURE_NO_WARNINGS 1
#define L 3
#define W 3
void initboard(char board[L][W], int l, int w);
void printboard(char board[L][W], int l, int w);
void playermove(char board[L][W], int l, int w);
void computermove(char board[L][W], int l, int w);
char judge(char board[L][W], int l, int w);
void game(void);

5.2初始化棋盘

(1)要求

把棋盘都初始化为空格

(2)代码实现
void initboard(char board[L][W], int l, int  w)
{
	int x = 0, y = 0;
	for (x = 0; x < l; x++)
		for (y = 0; y < w; y++)
			board[x][y] = ' ';
}

5.3 打印棋盘

    (1)要求

1. 打印出棋盘中的元素。

2. 利用---,|模拟出棋盘框。

(2)实现
void printboard(char board[L][W], int l, int w)
{
	int i = 0;
	for (i = 0; i < l-1; i++)
	{
		for (int j = 0; j < w-1; j++)
			printf(" %c |", board[i][j]);
		printf(" %c ", board[i][w-1]);
		printf("\n");                      //打印前两行
		for(int j=0;j<w-1;j++)
		printf("---|");
		printf("---\n");
	}
	for (int j = 0; j < w-1; j++)
		printf(" %c |", board[i][j]);//打印最后一行
	printf(" %c ", board[i][w - 1]);
	printf("\n");
}

(3)效果展示

5.4玩家下棋

(1)要求

1.若输入坐标不在棋盘范围中,或该位置已经有棋了,提醒玩家重新输入

2.坐标有效则更改二维数组中存放的元素为玩家对应符号‘#’

(2)代码实现

void playermove(char board[L][W], int l, int w)
{
	int x, y;
again:	printf("玩家下棋\n请输入坐标:>");
		scanf("%d %d", &x, &y);
		if (x <= l && x > 0 && y <= w && y > 0)
		{
			if (board[x-1][y-1] == ' ')
				board[x-1][y-1] = '#';//坐标有效,修改数组
			else
			{
				printf("这个地方有棋子了,换个地方吧!\n");
				goto again;
			}
		}
		else
		{
			printf("下错了,重新下吧!\n");
			goto again;
		}
}

      (3)效果展示

5.4电脑下棋

(1)要求

1.若输入坐标不在棋盘范围中,或该位置已经有棋了,则电脑重新输入

2.坐标有效则更改二维数组中存放的元素为电脑对应符号‘*’

(2)代码实现   

void computermove(char board[L][W], int l, int w)
{
	printf("电脑下棋\n");
	int x, y;
	again:  x = rand() % 3 + 1, y = rand() % 3 + 1;//随机数产生坐标
	if (x <= l && x > 0 && y <= w && y > 0&&board[x - 1][y - 1] == ' ')
		board[x - 1][y - 1] = '*';
		else
		goto again;
}

(3)效果展示

5.6判断棋局情况

(1)要求

棋局有三种情况,平局,胜负,或还未结束,根据不同情况返回不同字符

(2)代码实现

char judge(char board[L][W], int l, int w)
{
	for (int i = 0; i < l; i++)
	{
		int j = 0;
		for ( j = 0; j < w-1; j++)
		{
			if (board[i][j] != board[i][j + 1])
				break;
		}
		if (j == w-1 && board[i][j - 1] != ' ')//检查是否有连成一行
			return board[i][j - 1];
	}
	for (int i = 0; i < l; i++)
	{
		int j = 0;
		for (j = 0; j < w-1; j++)
		{
			if (board[j][i] != board[j+1][i])//检查是否有连成一列
				break;
		}
		if (j == w-1 && board[j-1][i] != ' ')
			return board[j-1][i];
	}
	int x;
	for ( x = 0; x < l-1; x++)
		if (board[x][x] != board[x + 1][x + 1])//检查是否连成对角线
			break;
	if (x == l-1 && board[x - 1][x - 1] != ' ')
		return board[x - 1][x - 1];
	int y;
	for (y=l-1;  y>0; y--)
		if (board[y][y] != board[y-1][y-1])//检查是否连成另一条对角线
			break;
	if (y == 0 && board[y][y] != ' ')
		return board[y][y];
	for (int i = 0; i < l; i++)
	{
		int j = 0;
		for (j = 0; j < w; j++)
		{
			if (board[j][i] == ' ')
				return 'j';//检查棋盘满了没
		}
	}
	return 'p';//最后一种情况是平局
}

(3)效果展示

5.7调用各个函数实现游戏

void game()
{
	char b;
	char board[L][W] = { 0 };
	initboard(board, L, W);
	printboard(board, L, W);
	while (1)
	{
		playermove(board, L, W);
		printboard(board, L, W);
		 b = judge(board, L, W);
		if (b != 'j')
			break;
		computermove(board, L, W);
		printboard(board, L, W);
		b = judge(board, L, W);
		if (b != 'j')
			break;
	}
	if (b == '#')
		printf("你赢了\n");
	else if (b == '*')
		printf("你输了\n");
	else
		printf("平局\n");
}

6. 源码 

  (1)main.c

#include"test.h"
void menu()
{
	printf("*********************\n");
	printf("****开始   :1*******\n");
	printf("****结束   :0********\n");
	printf("*********************\n");
}
int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do {
        game();
		menu(); 
		printf("请选择:->");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始游玩三子棋,祝您好运!\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("请输入0 或 1 !\n");
			break;
		}
	} while (input);
	return 0;
}

(2)test.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define _CRT_SECURE_NO_WARNINGS 1
#define L 3
#define W 3
void initboard(char board[L][W], int l, int w);
void printboard(char board[L][W], int l, int w);
void playermove(char board[L][W], int l, int w);
void computermove(char board[L][W], int l, int w);
char judge(char board[L][W], int l, int w);
void game(void);

(3)test.c

#include"test.h"
void initboard(char board[L][W], int l, int  w)
{
	int x = 0, y = 0;
	for (x = 0; x < l; x++)
		for (y = 0; y < w; y++)
			board[x][y] = ' ';
}
void printboard(char board[L][W], int l, int w)
{
	int i = 0;
	for (i = 0; i < l-1; i++)
	{
		for (int j = 0; j < w-1; j++)
			printf(" %c |", board[i][j]);
		printf(" %c ", board[i][w-1]);
		printf("\n");
		for(int j=0;j<w-1;j++)
		printf("---|");
		printf("---\n");
	}
	for (int j = 0; j < w-1; j++)
		printf(" %c |", board[i][j]);
	printf(" %c ", board[i][w - 1]);
	printf("\n");
}
void playermove(char board[L][W], int l, int w)
{
	int x, y;
again:	printf("玩家下棋\n请输入坐标:>");
		scanf("%d %d", &x, &y);
		if (x <= l && x > 0 && y <= w && y > 0)
		{
			if (board[x-1][y-1] == ' ')
				board[x-1][y-1] = '#';
			else
			{
				printf("这个地方有棋子了,换个地方吧!\n");
				goto again;
			}
		}
		else
		{
			printf("下错了,重新下吧!\n");
			goto again;
		}
}
void computermove(char board[L][W], int l, int w)
{
	printf("电脑下棋\n");
	int x, y;
	again:  x = rand() % 3 + 1, y = rand() % 3 + 1;
	if (x <= l && x > 0 && y <= w && y > 0&&board[x - 1][y - 1] == ' ')
		board[x - 1][y - 1] = '*';
		else
		goto again;
}
char judge(char board[L][W], int l, int w)
{
	for (int i = 0; i < l; i++)
	{
		int j = 0;
		for ( j = 0; j < w-1; j++)
		{
			if (board[i][j] != board[i][j + 1])
				break;
		}
		if (j == w-1 && board[i][j - 1] != ' ')
			return board[i][j - 1];
	}
	for (int i = 0; i < l; i++)
	{
		int j = 0;
		for (j = 0; j < w-1; j++)
		{
			if (board[j][i] != board[j+1][i])
				break;
		}
		if (j == w-1 && board[j-1][i] != ' ')
			return board[j-1][i];
	}
	int x;
	for ( x = 0; x < l-1; x++)
		if (board[x][x] != board[x + 1][x + 1])
			break;
	if (x == l-1 && board[x - 1][x - 1] != ' ')
		return board[x - 1][x - 1];
	int y;
	for (y=l-1;  y>0; y--)
		if (board[y][y] != board[y-1][y-1])
			break;
	if (y == 0 && board[y][y] != ' ')
		return board[y][y];
	for (int i = 0; i < l; i++)
	{
		int j = 0;
		for (j = 0; j < w; j++)
		{
			if (board[j][i] == ' ')
				return 'j';
		}
	}
	return 'p';
}
void game()
{
	char b;
	char board[L][W] = { 0 };
	initboard(board, L, W);
	printboard(board, L, W);
	while (1)
	{
		playermove(board, L, W);
		printboard(board, L, W);
		 b = judge(board, L, W);
		if (b != 'j')
			break;
		computermove(board, L, W);
		printboard(board, L, W);
		b = judge(board, L, W);
		if (b != 'j')
			break;
	}
	if (b == '#')
		printf("你赢了\n");
	else if (b == '*')
		printf("你输了\n");
	else
		printf("平局\n");
}

好啦好啦,终于写完了,完结撒花,感谢观看,下次再见

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在ubuntu22.04中借助docker实现安装、调试ros1.0

一.安装docker 参考&#xff1a;https://www.cnblogs.com/cqpanda/p/16247919.html 使用安装方法1直接安装&#xff0c;没出问题&#xff0c;我就继续了。出问题按方法2安装吧。 curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun 二.docker中安装ros1.…

101.对称二叉树

101.对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false提示&#xff1a; …

【C语言】epoll_wait / select

一、epoll_wait和select对比 1. 阻塞和非阻塞 在Linux C语言中进行socket编程时&#xff0c;epoll_wait 和 select 都是用于多路I/O复用的系统调用&#xff0c;但是它们的行为可以设置为阻塞和非阻塞模式&#xff0c;这取决于调用它们时所使用的参数。 让我们分别看看 epoll…

[网络安全] IIS----WEB服务器

一、 WEB服务器 WEB服务器 也叫网页服务器和 HTTP服务器使用协议: HTTP(端口:80) 或 HTTPS(端口443)浏览器:HTTP客户端网站: 一个或多个网页组成的集合 二、HTTP和HTTPS协议: HTTP : 是 HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09;的简写&#xff0c;…

Maven安装,学习笔记,详细整理maven的一些配置

Maven 1. 初识Maven 2. Maven概述 Maven模型介绍 Maven仓库介绍 Maven安装与配置 3. IDEA集成Maven 4. 依赖管理 01. Maven课程介绍 1.1 课程安排 学习完前端Web开发技术后&#xff0c;我们即将开始学习后端Web开发技术。做为一名Java开发工程师&#xff0c;后端 Web开发技术…

Solon 开源框架讲的“三源合一”是怎么回事?

1、什么是“三源合一”&#xff1f; “三源合一”&#xff0c;是 Solon 应用开发框架早期的一个架构想法。是指 Http、Socket、WebSocket 几个不同的通讯信号&#xff0c;进行统一架构处理…并且小巧。 对于 Socket 和 WebSocket&#xff0c;在原 消息监听 的模式之外增加了 M…

Wireshark网络协议分析 - Wireshark速览

在我的博客阅读本文 文章目录 1. 版本与平台2. 快速上手2.1. 选择网络接口进行捕获&#xff08;Capture&#xff09;2.2. 以Ping命令为例进行抓包分析2.3. 设置合适的过滤表达式2.4. 数据包详情2.5. TCP/IP 四层模型 3. 参考资料 1. 版本与平台 Wireshark是一个开源的网络数据…

vue——实现多行粘贴到table事件——技能提升

最近在写后台管理系统时&#xff0c;遇到一个需求&#xff0c;就是要从excel表格中复制多行内容&#xff0c;然后粘贴到后台系统中的table表格中。 如下图所示&#xff1a;一次性复制三行内容&#xff0c;光标放在红框中的第一个框中&#xff0c;然后按ctrlv粘贴事件&#xff0…

机器学习复习(6)——numpy的数学操作

加减法运算 # 创建两个不同的数组 a np.arange(4) #list(0,1,2,3 b np.array([5,10,15,20]) # 两个数组做减法运算 b-a 运行结果&#xff1a; 计算数组的平方 #b*2代表数组b每个元素乘以2 #b**2代表数组b每个元素的2次方 b**2 运行结果&#xff1a; 计算数组的正弦值 #…

简单高效 Learn LaTeX 013 - LaTex FloatingBody Tables (44 mins) 浮动体表格

浮动体是LaTex中的一个重要概念&#xff0c;这个视频演示了以浮动体为载体的表格的排版应用。 https://www.douyin.com/user/self?modal_id7305874487138913574&showTabpost

机器学习的精髓-梯度下降算法

目 1. 梯度下降算法2. 梯度下降求解3. 总结 1. 梯度下降算法 梯度下降算法是一种优化算法&#xff0c;用于最小化函数的数值方法。它通过沿着函数梯度的反方向来更新参数&#xff0c;以逐步减小函数值。这一过程重复进行直到达到收敛条件。梯度下降算法有多种变体&#xff0c;…

02、全文检索 ------ Solr(企业级的开源的搜索引擎) 的下载、安装、Solr的Web图形界面介绍

目录 Solr 的下载和安装Solr的优势&#xff1a;Lucene与Solr 安装 Solr1、下载解压2、添加环境变量3、启动 Solr Solr 所支持的子命令&#xff1a;Solr 的 Core 和 Collection 介绍Solr 的Web控制台DashBoard&#xff08;仪表盘&#xff09;Logging&#xff08;日志&#xff09…

vscode 插件 Tailwind CSS IntelliSense 解决 class 提示问题

问题描述&#xff1a; 如下写js字符串是没有class智能提示的&#xff1a; const clsName bg-[#123456] text-[#654321] return <div className{clsName}></div>解决方案&#xff1a; 安装 clsx 依赖 pnpm i clsx设置 vscode 的 settings.json {"tailwin…

150基于matlab的凸轮轮廓的设计计算与绘图计算此结构的最优化参数

基于matlab的凸轮轮廓的设计计算与绘图计算此结构的最优化参数&#xff0c;根据其原理输出推程和回程的最大压力角、最小曲率半径等相关结果。程序已调通&#xff0c;可直接运行。 150 凸轮轮廓的设计 结构的最优化参数 (xiaohongshu.com)

外星人入侵(python)

前言 代码来源《python编程从入门到实践》Eric Matthes 署 袁国忠 译 使用软件&#xff1a;PyCharm Community Editor 2022 目的&#xff1a;记录一下按照书上敲的代码 alien_invasion.py 游戏的一些初始化设置&#xff0c;界面的大小&#xff0c;标题 import sys import …

spring boot 项目中的异常处理

出现异常&#xff1a; 怎样定义全局异常处理器 新建一个类&#xff0c;加上注释两个 ControllerAdvice(basePackages"com.example.controller") public class GlobalExceptionHandler {private static final Log log LogFactory.get();//统一异常处理ExceptionHandl…

SOLIDWORKS Simulation 2024增强新功能

SOLIDWORKS 2024 新功能前瞻| SOLIDWORKS Simulation 功能增强 • 性能增强功能 • 壳体的接合交互 • 网格性能 • 欠约束实体检测 • 增强型轴承接头 • 收敛检查图解 • 去耦合混合自由体模式 • 复制算例时排除网格和结果 • 新增在网格化后及分析完成后自动保存模…

【Tomcat与网络10】Tomcat I/O和线程池的并发调优

前面我们看了提高Tomcat启动速度的措施&#xff0c;这里我们看一下如何提高Tomcat的性能。 Tomcat 的调优涉及 I/O 模型和线程池调优、JVM 内存调优以及网络优化等&#xff0c;今天我们来聊聊 I/O 模型和线程池调优&#xff0c;由于 Web 应用程序跑在 Tomcat 的工作线程中&…

给定n个结点的树,u,v两个结点可以配对当且仅当u不是v的祖先且v不是u的祖先,每个结点最多与一个结点配对,求最大配对个数

题目 思路: #include <bits/stdc++.h> using namespace std; #define int long long typedef long long ll; #define pb push_back #define lson p << 1 #define rson p << 1 | 1 #define fi first #define se second const int maxn = 1e6 + 5, maxm = 5e…

【破事水】Java Gradle 无法引入同名不同版本的两个包

此问题水于 2024 年 01 月&#xff0c;假如后面 gradle 出了什么好方法能解决这个问题&#xff0c;家祭无忘告乃翁&#xff0c;提前谢过看到这篇的各位大佬了。 结论 先说结论&#xff0c;Java 因为包名定义等原因&#xff0c;对同名包在编译时只能编译一个版本&#xff0c;具…