三子棋游戏小课堂

news2024/11/15 12:29:46

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

今天的主菜是,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");
}

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

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

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

相关文章

SpringBoot集成H2数据库

1&#xff09;添加H2的依赖 <dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>compile</scope> </dependency>2&#xff09;添加连接配置&#xff0c;启用web控制台 spring:datasource:url…

短信验证码接口被恶意攻击了该怎么办?

在企业运行的时候&#xff0c;安全意识和风险防范机制一定要做好。在2019年SUBMAIL短信平台就有几个客户的短信验证码接口遭到了恶意攻击&#xff0c;如果没有做好防范就会造成一定程度的损失。 那么&#xff0c;当短信验证码接口被恶意攻击的时候&#xff0c;该怎么办呢&#…

【OCR软件进化史】文字、表格、公式图片识别并与ChatGPT交互

第1年 由于日常工作需要大量的文本处理&#xff0c;身为一个全栈pythoner是绝不允许手动复制粘贴。 于是&#xff0c;在2021年&#xff0c;封装了第1版的文字、表格、公式图片识别工具&#xff08;第1版&#xff09;&#xff1a; 第1版做的比较粗糙&#xff0c;就是封装了百度…

STC8G1K17A点灯

目录 1设计目的 2STC8G1K17A介绍 3代码实现 4效果测试 1设计目的 通用的STC89C52单片机由于封装太大&#xff0c;而且还需要外加晶振才能工作&#xff0c;对于一些要求不高的场合&#xff0c;就显得很笨重&#xff0c;所以&#xff0c;此次设计就是寻找一个代替产品&#x…

Kotlin 协程:用源码来理解 ‘viewModelScope‘

Kotlin 协程&#xff1a;用源码来理解 ‘viewModelScope’ Kotlin 协程是 Kotlin 语言的一大特色&#xff0c;它让异步编程变得更简单。在 Android 开发中&#xff0c;我们经常需要在后台线程执行耗时操作&#xff0c;例如网络请求或数据库查询&#xff0c;然后在主线程更新 UI…

PHP的线程安全与非线程安全模式选哪个

曾经初学PHP的时候也很困惑对线程安全与非线程安全模式这块环境的选择&#xff0c;也未能理解其中意。近来无意中看到一个教程对线程安全&#xff08;饿汉式&#xff09;&#xff0c;非线程安全&#xff08;懒汉式&#xff09;的描述&#xff0c;虽然觉得现在已经能够很明了透彻…

Python算法题集_最大子数组和

本文为Python算法题集之一的代码示例 题目53&#xff1a;最大子数组和 说明&#xff1a;给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。…

RS485自动收发电路震荡的问题

电路 设计初衷 电源5V 选择5V的原因&#xff0c;差分2.5V比1.5V可以提高传输能力 TTL输入 3.3V电平满足需求 TTL输出 4.5V了&#xff0c;MCU是3.3V平台 这样就分为两种情况 MCU接收端可以容忍5V输入 MCU接收端不可以容忍5V输入&#xff0c;就要进行电压转换&#xff0c;我这里使…

【C++】STL优先级队列(priority_queue)

priority_queue 基本介绍 priority_queue就是优先级队列。其头文件就是queue&#xff0c;但是队列和优先级队列关系不大&#xff0c;两个是不同的数据结构。但二者都是适配器&#xff0c;容器适配器。 优先级队列中存放的数据是有优先级的。 其内部有以下成员方法&#xff0c…

跟着cherno手搓游戏引擎【17】整理代码、timestep和transform

这里就不分部走了&#xff0c;直接上代码。 全局&#xff1a; YOTO.h:添加renderer的头文件&#xff1a; #pragma once//用于YOTO APP#include "YOTO/Application.h" #include"YOTO/Layer.h" #include "YOTO/Log.h"#include"YOTO/Core/T…

V2X,启动高增长引擎

车载通讯的下一个新周期&#xff0c;毋庸置疑是V2X。从4G、5G再到C-V2X&#xff0c;是车载通讯逐步从信息娱乐、行车数据监控到万物互联的关键。 去年5月&#xff0c;全球车载通讯芯片巨头—高通公司宣布&#xff0c;与以色列车联网&#xff08;V2X&#xff09;芯片设计公司Aut…

DevOps落地笔记-05|非功能需求:如何有效关注非功能需求

上一讲主要介绍了看板方法以及如何使用看板方法来解决软件研发过程中出现的团队过载、工作不均、任务延期等问题。通过学习前面几个课时介绍的知识&#xff0c;你的团队开始源源不断地交付用户价值。用户对交付的功能非常满意&#xff0c;但等到系统上线后经常出现服务不可用的…

扣库的函数经验

有的库确实可以提出来的 比如这个库 GitHub - intel/x86-simd-sort: C template library for high performance SIMD based sorting algorithms 根据自己的需要是可以&#xff0c;把内容抠出来的&#xff0c;重新build的。 我就自己新建了一个vs的工程&#xff0c;然后把源…

将java对象转换为json字符串的几种常用方法

目录 1.关于json 2.实现方式 1.Gson 2.jackson 3.fastjson 3.与前端的联系 1.关于json JSON是一种轻量级的数据交换格式。它由Douglas Crockford在2001年创造。JSON的全称是JavaScript Object Notation&#xff0c;它是一种文本格式&#xff0c;可以轻松地在各种平台之间传…

【GEE】基于GEE可视化和下载Landsat8 L2A数据(镶嵌、裁剪)

之前发过一篇使用GEE下载Landsat8的文章&#xff0c;然后有很多小伙伴私信我各种问题&#xff0c;如L1C、L2数据代码怎么修改&#xff0c;如何镶嵌&#xff0c;如何去云、 如何裁剪等一系列问题。正好快过年了&#xff0c;手头的事也没有多少了&#xff0c;所以这两天整理了一下…

考研高数(数列极限之f(xn)和{xn}的关系)

说白了&#xff0c;f(xn)是复合函数&#xff0c;是f(x)与{xn}的复合函数。&#xff08;复合函数的单调性有同增异减的原则&#xff09; 例题1&#xff1a;【可以用同增异减的原则&#xff0c;迅速解答&#xff08;有不合理的地方&#xff0c;请各位大佬指正&#xff01;&#…

【操作系统】FileOutputStream的flush操作有时不生效

按照我们的理解&#xff1a;FileOutputStream的flush()方法的作用就是将缓冲区中的数据立即写入到文件中&#xff0c;即使缓冲区没有填满。这样可以确保数据的及时写入&#xff0c;而不需要等待缓冲区填满或者调用 close() 方法关闭流时才写入。真的是这样吗&#xff1f;&#…

dv和ov通配符SSL证书的区别

SSL数字证书是一种数字证书&#xff0c;可以保护网站传输数据安全以及对服务器身份进行验证&#xff0c;SSL证书有很多种&#xff0c;而通配符证书则是其中的一种特殊类型。SSL证书旗下的通配符SSL证书随着互联网的发展&#xff0c;颁发量也越来越多&#xff0c;为了使用户选择…

websocket编写聊天室

【黑马程序员】WebSocket打造在线聊天室【配套资料源码】 总时长 02:45:00 共6P 此文章包含第1p-第p6的内容 简介 温馨提示&#xff1a;现在都是第三方支持聊天&#xff0c;如极光&#xff0c;学这个用于自己项目完全没问题&#xff0c;大项目不建议使用 需求分析 代码

Celeryconfig配置文件

Celery配置文件 本篇介绍Celery配置文件相关&#xff0c;celeryconfig.py Celeryconfig.py 在上篇celery基础用法中&#xff0c;是这样使用celery的实例化的。 # tasks.py 文件名需与实例化对象第一个参数一致 import time from celery import Celeryredis_url redis://Pa…