記事の最後には、Snake のコードの概要があり、コードには非常に詳細なコメントが付いています!!!記事の最後には、Snake のコードの概要があり、コードには非常に詳細な
コメントがあります!!!
コメント!!!
コードテキストは簡単ではありません。無料の小さなスターと無料のいいねを付けて、フォローしてください(⑅•͈ᴗ•͈)。:*♡
無駄に売春婦になるなよ (⁍̥̥̥᷄д⁍̥̥̥᷅ ू ) 悲しい
目次
2.2.3 ルールインターフェイスのフローチャートを表示する
カリキュラム 設計タスクブック |
デザインタイトル: スネークファイト 設計内容と要件: デザイン内容: C プログラミング言語を使用して、スネーク ゲーム機能を設計します。プロジェクトは主に、メニュー インターフェイス、ルール インターフェイス、メイン ゲーム インターフェイスの 3 つのインターフェイスに分かれています。 革新点: ヘビの体の単色をゲームの進行に応じて変化する虹色に変更し、速度メカニズムとスコア報酬メカニズムを変更し、マウスインタラクティブメニューを追加してゲーム体験を向上させます。 設計要件: ゲーム デザインを通じてC言語の知識を強化し、合理的な標準で関数を作成し、それらを正しく呼び出すことができます。easyx を使用して拡張コンテンツを追加し、使用される関数のメソッドを理解します。 設計でエラーが発生した場合は、適時にデバッグおよび分析し、データを参照し、同じ関数を複数の方法で比較および使用して、コードが正しく、正常に実行されていることを確認します。 指導者: 年月日 _ |
1 被験者の分析
1.1 研究の背景と現状
コンピュータ産業の急速な発展に伴い、多くの人気のあるプログラミング言語が登場しましたが、C言語は広く使用されている高級プログラミング言語として、特に重要なプログラム開発と学習が重要であり、高い描画能力、移植性、耐久性などの特徴を持っています。強力なデータ処理能力があり、システム ソフトウェア、グラフィックス、アニメーションの作成に適しています。
今日のゲームは人気の娯楽となっていますが、スネークは大衆の心理に適合し、幅広い層に適応し、娯楽性とインタラクティブ性が高く、人々の娯楽時間を豊かにすることができます。
小規模なゲームとしては、スネークは操作がシンプルで使いやすいです。ゲームの仕組みは非常に刺激的で、魅力的で中毒性があります。大規模なゲームの長期消費と比較して、スネークは断片的な娯楽時間に合理的であり、楽しむことができます。シンプルで人々のニーズに応えやすい。
この記事の主な目的は、C 言語で Snake ゲームを研究および設計し、EasyX Graphics Library の無料描画ライブラリを使用してゲーム画面を実現し、関数の設計と呼び出しを行い、ゲームのルールと操作メカニズムを定式化し、出力することです。 Windowsコンソールホスト上の画面を表示してゲーム操作を実現します。
1.2 研究の意義と研究の手順
意義:
ペースの速い社会では、人々の時間はよりコンパクトになり、娯楽や余暇の時間も非常に逼迫しています。幅広い観客を対象とした大規模なゲームの場合、ライトなゲームや速いゲームは食欲とより密接に関係しており、断片化された時間、ペースの速いエンターテイメント体験でユーザーがより満足できるようになります。
スネーク ミニゲームを通じて、人々は余暇を楽しむだけでなく、ゲームのスコアを記録し、成功するために課題で自分自身を向上させることもできます。同時に、C 言語のコース設計を学習し、スネーク ゲームを作成することで思考力を鍛え、コードの使用に慣れることができ、将来のプロジェクト開発や総合的な開発のための経験を蓄積するのに役立ちます。
研究の手順:
(1) デザイン: ゲームの最も重要な部分はインターフェイス表示デザインです。ゲーム ウィンドウのサイズとテキスト コンテンツ プロンプトを考慮する必要があります。これにより、ユーザーがゲームを開いたときに良好な実行エクスペリエンスを得ることができ、役割が明確になります。各機能の説明やゲームの操作方法などを説明します。2 つ目は、プレーヤーがより良いインタラクティブなフィードバックを得ることができるように、スムーズで優れたキーボードとマウスの操作を設計することです。
(2) ゲーム プログラムのテストは重要なステップです。ゲーム関数が追加されるたびに、サンプルを使用してテストして、コードにエラーがないこと、Snake の実行プロセスが正しいこと、ゲーム インターフェイスの出力に問題がないことを確認する必要があります。また、キーボードとマウスの対話では、その流暢性と安定性を確保し、ユーザーに優れたゲーム体験を提供します。
2 設計概要
2.1 プロジェクトの具体的な内容
このプロジェクトでは、C プログラミング言語と EasyX グラフィック ライブラリを使用して、ヘビ ゲーム プログラムを設計します。プロジェクトは主に、メイン メニュー インターフェイス、ルール インターフェイス、ゲーム開始インターフェイスの 3 つのインターフェイスに分かれています。
メイン メニュー インターフェイスを介してゲーム開始インターフェイスに入り、マウス インタラクションを通じてボタンをクリックしてゲームを開始し、ゲームをリアルタイムで得点することができます。ビュー ルール インターフェイスでは、スネーク ゲーム ルール設定を確認し、ゲーム履歴の最高スコアを確認できます。ゲームを終了したい場合は、メインメニューの終了ボタンを選択してプログラムを終了します。
2.2 システムブロック図
2.2.1 プログラム構造図
図 2-1 に示すように、スネーク ゲーム プログラムは主に、メイン メニュー インターフェイス、ゲーム インターフェイス、ルール インターフェイス、ゲーム終了インターフェイスで構成されます。
図 2-1 プログラム構造図
2.2.2 ゲームのフローチャート
ゲーム本体は、ゲーム初期化機能、画面表示機能、楽譜読み書き機能、インタラクション機能といういくつかの機能から構成されており、ゲーム動作のフローチャートは図のようになります。 2-2:
図 2-2 ゲームのフローチャート
2.2.3 ルールインターフェイスのフローチャートを表示する
ビュー ルール インターフェイスは、最高スコア、インターフェイス テキスト出力、およびマウス ボタン インタラクションを読み取ることによって実装されます。構造マウスを定義し、その動作を判断します。ボタンをクリックしない場合は、次のように何も操作せずにルール インターフェイスに入ります。図 2-3 に示すように:
図 2-3 ルール インターフェイスのフローチャート
2. システムモジュール部門
コース プロジェクトの設計では、スネーク ゲームは主に 3 つのインターフェイス、つまりメニュー インターフェイス、ルール インターフェイス、メイン ゲーム インターフェイスに分かれています。モジュールは、メインメニューモジュール、ゲーム初期化、画面表示、ヘビ移動モジュール、キーボード入力に関連する更新(つまり、キーボードがヘビの移動方向を制御する)、入力に関係しない更新(移動速度制御)、報酬に分かれています。メカニズムとスコアモジュール
メイン メニュー インターフェイスのデザインでは、easyx グラフィック ライブラリを使用してボタン オプションをデザインし、インターフェイスに色を付けます。また、マウスの左ボタンとマウスのクリック位置の動作を監視することで、ユーザーが選択したボタン オプションを判断します。インタラクションと完全なインターフェイスジャンプを実現するために
「ゲーム開始」オプションが選択されている場合、ゲーム開始関数に入り、ゲームを初期化して最高スコアを読み取り、スネークと画面を初期化してからループに入ります。ゲームの失敗条件が満たされていない場合、インターフェースは常に描画を更新します。ゲームを続けてください。
その中で、スネークゲームの速度メカニズムと報酬メカニズムがそれぞれ改善されており、速度は矢印キーを押したままにして前に加速するというニーズを満たすことができ、食べ物を食べるほど速度が速くなります; スコア報酬メカニズムは一定のしきい値制限を満たしており、食べた食べ物が一定のレベルに達すると、スコアが倍増してボーナス ポイントが増加します。
ゲーム障害精算インターフェースに、このゲームでのユーザーのスコアをより直感的に確認できるようにスコア表示を追加しました。スコアモジュールでは、txt ファイルが読み書きされます。プレイヤーのスコアが最高スコアより大きい場合、このゲームのスコアは最高スコアをカバーします。
3 設計の詳細な説明
3.1 メインメニューのインターフェース設計の説明
3.1.1 設計の説明
メイン メニュー インターフェイスは、グラフィック ライブラリの描画機能を使用してボタンの四角形を描画し、プレーヤーがその機能を理解できるようにボタンにプロンプト テキストを出力し、while 関数を通じてマウス メッセージを常に監視します。マウスボタンをクリックしてif判定を行い、いずれかのボタンのクリック位置と一致した場合、if文に関数を入力してジャンプ機能を実現します。
3.1.2 機能表示
メイン メニュー インターフェイスを図 3-1 に示します。
図 3-1 メイン メニュー インターフェイス
3.2 ルールインターフェイスの設計説明を表示する
3.2.1 設計の説明
ビュールールインターフェース機能:ビュールールインターフェースでは、プレイヤーはゲームのルールやキー操作を理解することができると同時に、このインターフェース上に最高スコアが表示されるため、プレーヤーはゲームの目的を理解した上でゲームを行うことができます。関連するルールがある場合、プレーヤーはボタンをクリックしてメイン メニューから「ゲームの開始」または「ゲームの終了」を選択して戻ります。
具体的な実装: 実現したインターフェース表示はメインメニューと一致しており、最高スコアを読み取るには、書き込みスコア読み書き機能を使用して、インターフェース上のtxtファイル内のスコアを読み取って表示します。
3.2.2 機能表示
ルールを表示するためのインターフェイスを図 3-2 に示します。
図 3-2 ビュー ルール インターフェイス
3.3 ゲームインターフェイスの設計手順の開始
3.3.1 設計の説明
ゲームインターフェイス機能を開始します。ゲームの本体を認識し、ヘビ、食べ物とゲームインターフェイスを描きます。キーボード操作で貪欲なヘビが食べ物を食べるように動きます。インターフェイスには最高スコアが表示され、プロセスの進行に応じてリアルタイムでスコアが記録されます。ゲームが終了すると決済画面がポップアップ表示されます
具体的な実装: キャンバスのサイズを設定してインターフェイスを決定し、水平線と垂直線を引いてキャンバスを小さな正方形に分割し、固定ピクセル値を計算して、各長方形の正方形を 1 つずつ正方形配列にマッピングします。ゲームの初期化時に配列を走査してヘビと餌を描画し、その後は画面が更新されるたびに配列を走査してヘビの長さと餌の位置を更新します。
リアルタイムレコードスコアは、int変数を定義し、スコアの仕組みに従って対応する値を増加させた後、char型に変換して文字配列に格納し、画面に出力します。
ゲーム決済インターフェースはスネークヘッドの位置を判断し、グローバル変数の値を変更し、ゲームループから抜け出し、対応するテキストを出力します。
3.3.2 機能表示
ゲーム インターフェイスを図 3-3 と図 3-4 に示します。
図 3-3 ゲームインターフェイス
図 3-4 ゲーム決済インターフェース
4 結論
C 言語コースの 1 学期の学習を通じて、チームメンバーと私は C 言語についての理解を深めました。最初から何も分からず、自分で少しずつ調べていきました。本で学んだことだけではまだまだ不十分で、課外学習が必要なことがまだまだたくさんあることがわかりました。Snakeについてはその実現原理を知り、プログラムモジュール設計やデータ構造設計の簡単な分析を学びました。そしてソースコード解析を通じて各モジュールの実装方法を説明します。グラフィックス機能の一部は、いくつかのモジュールの実装に組み込まれています。この記事の執筆プロセスを通じて、次の知識ポイントを習得しました。
1. グラフィックスシステムの初期化とシャットダウン
2. 各種描画機能の利用
3. 構造の定義
5. 関数のネストと呼び出し
6. キーボード操作
一般的に、プログラミングは依然として忍耐力が必要な仕事であり、特に見つけられないバグがある場合は、特に落ち着いて勉強する必要があります。多くの場合、それを変更する忍耐力がありません。この学習により、私たちのグループの忍耐力が大幅に磨かれ、多くのことを得ることができました。このコース設計で、私たちは C 言語の知識を統合し、合理的な方法で関数を記述して正しく呼び出すことを学び、easyx を使用して次のことを実行できるようになりました。性的なコンテンツを増やし、拡大するために最も重要なことは、自分自身の欠点を発見することです。
今後もたゆまぬ努力を続け、練習を続け、常に自分自身を突破し、より良い作品を作るよう努めてまいります。
付録:
スネークのプログラムは次のとおりです。
#include <graphics.h>
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <cstdio>
#define Width 40 //宽40格
#define Height 30 //高30格
#define Size 20 //格子大小:20
int blocks[Width][Height] = {0}; //用以表示所有方格
char moveDir; //表示运动方向
char oldmove; //旧的移动方向
int fx, fy; //food食物坐标
int addspeed = 15; //控制初始速度
int failure = 0; //用以判断游戏是否失败,失败赋值为 1
int score = 0; //记录分数
int max = 0; //记录最高分
int k = 1; //奖励机制初始值
char num[20]; //输出分数数组
char best[20]; //最高分数组
void initGame();
void show(); //图像绘制更新显示函数
void WithInput(); //与输入有关的更新
void WithoutInput(); //与输入无关的更新
void movesnake(); //蛇的移动函数
void readscore(); //读取分数
void writescore(); //写入分数
void ShowWord(); //界面文字
void drawmenu(); //主菜单
void gamestart(); //开始游戏
void seerule(); //查看规则
void back(); //退出游戏
int main() {
drawmenu();
return 0;
}
void initGame() {
int i;
initgraph(1000, 600); //①初始化绘图窗口,格子个数乘格子大小即为长度
setbkcolor(CYAN); //设置背景颜色
BeginBatchDraw(); //easyx中实现批绘图功能的函数,可以消除图像闪烁
cleardevice(); //使用当前背景色清空绘图设备
setlinecolor(WHITE); //划线颜色为白色
for (i = Size; i < Width * Size+1; i += Size) { //用for循环绘制多条线
line(i, 0, i, Height * Size); //竖线坐标从x1(i,0)-> y1(i,Height * Size)
}
for (i = Size; i < Height * Size; i += Size) {
line(0, i, Width * Size, i); //横线坐标从x2(0,i) -> y2(Width * Size, i)
}
moveDir = oldmove = 'd'; //初始化默认蛇行进方向朝右
blocks[Width / 2][Height / 2] = 1; /*正中间画蛇头,蛇为赋值的方格
0则为空白区域*/
for (i = 1; i < 4; i++) {
blocks[Width / 2 - i][Height / 2] = i + 1; //y坐标不变,更改x坐标,在蛇头后方画蛇身
}
srand(time(0)); //srand函数产生一个时间种子,从而达到真正的随机效果
fx = rand() % (Width - 1) + 1; //随机数除39取余并+1,则为食物所生成的格子x坐标
fy = rand() % (Height - 1) + 1; //随机数除取余并+1,则为食物所生成的格子y坐标
}
void show() {
cleardevice();
for (int i = 0; i < Width; i++) { //遍历所有方格,更新蛇的颜色
for (int j = 1; j < Height; j++) {
if (blocks[i][j] != 0) {
setfillcolor(HSVtoRGB(blocks[i][j] * 10, 0.9, 1)); //HSV转RGB颜色,色调H 0°->360°,此处设置每长一个蛇身,提升10°色调,饱和度0.9,明度1
}else{
setfillcolor(CYAN); //否则更新为正常背景颜色
}
fillrectangle(i * Size, j * Size, (i + 1) * Size, (j + 1) * Size); //填充,(参数为左上角和右下角坐标)
}
}
setfillcolor(LIGHTGREEN); //食物颜色
fillrectangle(fx * Size, fy * Size, (fx + 1) * Size, (fy + 1) * Size);
ShowWord();
FlushBatchDraw(); /*BeginBatchDraw执行后,任何绘图操作都将暂时不输出到绘图窗口上
直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。*/
}
void ShowWord() {
if (failure) {
settextcolor(LIGHTRED); //设置字体颜色
settextstyle(80, 0, _T("宋体")); //设置字体样式
setbkmode(TRANSPARENT);
outtextxy(240, 220, "游戏失败");
settextstyle(40, 0, _T("宋体"));
sprintf(num, "%d", score); //将int转换为char并存入num中
outtextxy(260, 360, "分数:"); //显示的字体及坐标
outtextxy(380, 360, num);
}
else { //②
settextcolor(BLACK); //设置分数颜色
settextstyle(25, 0, _T("隶书")); //设置字体样式
setbkmode(TRANSPARENT); //设置当前设备图案填充和文字输出时的背景模式,THANSPARENT为透明背景
sprintf(num, "%d", score); //将int转换为char并存入num中
outtextxy(860, 40, "分数:"); //显示的字体及坐标
outtextxy(940, 42, num);
outtextxy(845, 73, "最高分:");
sprintf(best, "%d", max);
outtextxy(940, 75, best);
}
}
void readscore() { //③
FILE* fpread = fopen("score.txt", "r"); //以只读的方式打开文件
if (fpread == NULL) {
return;
}
fscanf(fpread, "%d", &max);
fclose(fpread);
}
void writescore() {
FILE* fpWrite = fopen("score.txt", "w"); //"w"打开并写入文本文件.(若不存在则新建,反之,则从头写,覆盖原内容)
if (fpWrite == NULL) {
return ;
}
fprintf(fpWrite, "%d", score);
fclose(fpWrite);
}
void WithInput() {
if (_kbhit() && failure == 0) {
//键盘输入控制蛇的方向
char input = _getch();
if (input == 'a' || input == 's' || input == 'd' || input == 'w') {
moveDir = input;
//设定规则:当向某一方向行动时,按下反向键不起作用(防止误触导致判断为咬到蛇身游戏失败),强制将按下的反向键变为当前运动方向
if (moveDir == 'a' && oldmove == 'd') {
moveDir = 'd';
}
else if (moveDir == 's' && oldmove == 'w') {
moveDir = 'w';
}
else if (moveDir == 'd' && oldmove == 'a') {
moveDir = 'a';
}
else if (moveDir == 'w' && oldmove == 's') {
moveDir = 's';
}
else {
oldmove = input;
}
movesnake();
}
}
}
void WithoutInput() {
if (failure) { //先判断是否失败,失败则返回
return;
}
//Sleep(100); //更新速度控制蛇的移动速度,但使用sleep会产生键盘控制与画面的延迟,所以不使用
//movesnake();
static int speed = 1; //设置一个静态变量speed,利用循环特定次数来触发movesnake函数
speed++;
if (speed == addspeed) { //每15帧移动一次,同时实现长按方向键加快蛇的移动速度
movesnake();
speed = 1;
}
}
void movesnake() {
int i, j;
//对蛇进行更新,蛇每个格数值都+1,以便后面预备一个数值为1的新蛇头,当吃到食物时,新蛇头改变颜色加入蛇身中
for (i = 0; i < Width; i++) {
for (j = 0; j < Height; j++) {
if (blocks[i][j] != 0) {
blocks[i][j]++;
}
}
}
int oldhx, oldhy, oldtx, oldty; //旧蛇头和旧蛇尾的坐标
int tailblock = 0;
for (i = 0; i < Width; i++) {
for (j = 0; j < Height; j++) {
if (tailblock < blocks[i][j]) {
tailblock = blocks[i][j]; //遍历找出最大值即为蛇尾
oldtx = i;
oldty = j;
}
if (blocks[i][j]==2) { //寻找旧蛇头
oldhx = i;
oldhy = j;
}
}
}
//根据蛇的运动方向来赋值新蛇头的xy坐标
int newhx = oldhx, newhy = oldhy; //定义新蛇头
switch (moveDir) {
case'a':
newhx -= 1;
break;
case's':
newhy += 1;
break;
case'd':
newhx += 1;
break;
case'w':
newhy -= 1;
break;
}
//判断游戏是否失败
if (newhx >= Width || newhx < 0 || newhy >= Height || newhy < 0 || blocks[newhx][newhy] != 0) {
failure = 1;
return;
}
//令蛇头方格值为1
blocks[newhx][newhy] = 1;
//对吃到食物以及蛇尾的处理 ⑤
if (newhx == fx && newhy == fy) { //吃到食物,重新随机数生成新食物坐标
score = score + k; //吃到食物分数+k
if (score % 2 == 0) { //通过判断吃食物的数量来叠加奖励分
k = k + 1;
}
if (score > max) { //与最高分判断,条件成立才能覆盖最高分
writescore(); //写入最高分
}
//④
if (score) { //“加速”判断,通过判断分数增大的取值,加快蛇的运动速度,score不为0时进入该判断语句
if (score % 2 == 0) { //便于测试结果明显,设置每吃2个食物,蛇速度加快1帧
addspeed--;
}
}
fx = rand() % (Width - 1) + 1;
fy = rand() % (Height - 1) + 1;
}else{ //未吃到食物
blocks[oldtx][oldty] = 0;
}
}
void drawmenu() {
MOUSEMSG m; //定义结构体鼠标m
initgraph(600, 600); //定义画布大小
setbkcolor(CYAN); //设置背景颜色
cleardevice(); //使用当前背景色清空绘图设备,类似system(cls)的刷新
setfillcolor(WHITE); //方框颜色
fillrectangle(140, 50, 460, 170); //矩形左上角xy坐标和右下角xy坐标
fillrectangle(120, 220, 480, 350); //矩形左上角xy坐标和右下角xy坐标
fillrectangle(100, 400, 500, 540); //矩形左上角xy坐标和右下角xy坐标
settextcolor(BLACK); //设置字体颜色
settextstyle(50, 0, _T("楷体")); //设置字体格式
setbkmode(TRANSPARENT); //去除文字背景
outtextxy(200, 85, "开始游戏"); //文字输出位置的xy坐标
outtextxy(200, 260, "查看规则");
outtextxy(200, 445, "退出游戏");
while (1) {
m = GetMouseMsg(); //获取一个鼠标消息
if (m.x >= 140 && m.x <= 460 && m.y >= 50 && m.y <= 170) { //判断鼠标点击的位置
if (m.uMsg == WM_LBUTTONDOWN) { //当鼠标按下左键
gamestart(); //开始游戏
}
}
else if (m.x >= 120 && m.x <= 480 && m.y >= 220 && m.y <= 350) {
if (m.uMsg == WM_LBUTTONDOWN) { //当鼠标按下左键
seerule(); //查看规则
}
}
else if (m.x >= 100 && m.x <= 500 && m.y >= 400 && m.y <= 540) {
if (m.uMsg == WM_LBUTTONDOWN) { //当鼠标按下左键
back(); //关闭菜单退出游戏
}
}
}
}
void gamestart() {
readscore(); //读取最高分
initGame(); //游戏初始化
while (1) { //循环进行界面实时刷新,直至游戏判定失败
show(); //界面显示
WithoutInput(); //先调用与输入无关的更新
WithInput();
}
}
void seerule() {
MOUSEMSG m; //定义结构体鼠标m
readscore(); //读取历史最高分
initgraph(600, 600); //定义画布大小
setbkcolor(CYAN); //设置背景颜色
cleardevice(); //使用当前背景色清空绘图设备,类似system(cls)的刷新
setfillcolor(WHITE); //方框颜色
fillrectangle(100, 400, 500, 540); //矩形左上角xy坐标和右下角xy坐标
settextcolor(BLACK); //设置字体颜色
settextstyle(50, 0, _T("楷体")); //设置字体格式
setbkmode(TRANSPARENT); //去除文字背景
outtextxy(200, 445, "返回菜单");
settextcolor(BLACK); //设置字体颜色
settextstyle(30, 0, _T("楷体")); //设置字体格式
setbkmode(TRANSPARENT); //去除文字背景
outtextxy(45, 30, "WASD控制蛇移动,长按方向键可加速移动");
outtextxy(45, 80, "碰到墙壁游戏失败");
outtextxy(45, 130, "吃的食物越多,分数奖励越高");
outtextxy(45, 180, "历史最高分:");
sprintf(best, "%d", max);
outtextxy(220, 180, best);
while (1) {
m = GetMouseMsg(); //获取一个鼠标消息
if (m.x >= 100 && m.x <= 500 && m.y >= 400 && m.y <= 540) {
if (m.uMsg == WM_LBUTTONDOWN) { //当鼠标按下左键
drawmenu(); //返回主菜单
}
}
}
}
void back() {
closegraph(); //关闭画面
exit(0); //退出程序
}