検索
ホームページバックエンド開発C#.Net チュートリアルC# でジグソーパズルを作成するためのグラフィック コードとテキスト コードの共有 (パート 2)

この記事では主に、ジグソーパズルのC#コーディングの次の部分を詳しく紹介します。興味のある方は参考にしてください。

前書き: C# でのジグソーパズルのコードの作成 - C# でのプログラミングを実装します。 「ジグソー ゲーム」 (パート 1)、各モジュールのコードをアップロードしました。この記事では、読者が理解しやすく、学習しやすいように原理を詳細に分析します。このプログラムには多くの問題があります。それらを指摘し、一緒に学び、成長してください。

テキスト:

パズルは基本的に、そのゲームプレイ、開始、実行、終了を誰もが知っています。では、パズルを作りたいときはどうやって始めればよいのでしょうか?答えは、現実から始めて要件を記述します (要件をドキュメントとして記述するように努めてください)。包括的な要件があれば、信頼できる戦略を提供でき、それをコードに実装して最終的に作品にすることができます。

(1) 要件: (この要件はかなり読みにくく書かれており、大多数の初心者向けにカスタマイズされています。最も一般的な人々の思考とゲームに参加するプロセスに基づいています)

1.

写真 : 私たちはパズルをします 少なくとも絵があります

2. 切り抜き: パズルは絵ではありません。全体の絵を N*N 個の小さな絵に切り分ける必要があります

3. 整理する: これらの N*N の順序をシャッフルします。ただし、ゲームのルールに従って歩くことで復元できることを確認してください

4. 判定: パズルは成功と判断されます

5. インタラクション: ここではどのインタラクション方法を選択しますか?

6. 元画像の完全な

サムネイルを表示します

上記が基本機能、以下が拡張機能です

7. 歩数の記録: 完了するまでに何歩必要かを記録します

8.写真を変更する: 長い間遊んだ後、写真を変更できますか? (笑) 9. 難易度を選択します: 簡単すぎますか?欲しくない! 3*3の次は5*5があり、5*5の次は9*9があります。 ルームメイトは0ステップ以上の最高難易度に挑戦しました

。分析:

はい、要件。以下を含む実装方法 (実際の要件をコンピューターにマッピング) を分析できます。

1. 開発プラットフォーム: ここで C# 言語を選択します 1) 何を保存するか。 ?それを保管するためにどのような構造を使用しますか?要件を振り返ると、保存する必要のあるリソースがいくつかあることがわかります

画像: 画像

オブジェクト

を使用して

を保存します ユニット (元の画像を切り取った後のサブ画像のコレクション): カスタム

構造体

struct Node (Image オブジェクトを含む) 整形を使用して保存されたユニットの小さな画像と番号を保存するために使用されます (切り取った後、ゲームが完了したかどうかを確認しやすくするために、各小さなユニットに番号が付けられます)。 各ユニット(元の画像を切り取った後のサブ画像の集合):

二次元配列

を使用(ジグソー、バックギャモン、マッチ、連聯館、テトリスなどの平面格子ゲームを使用して保存できます)理由は? 似ているからです! ) を保存する モジュールの分割 (

正しい論理分割が拡張され、コミュニケーションがより明確になります

) を構築して、各モジュールに含まれる特定のアルゴリズムを実装します まず、プログラム モジュールは 4 つに分割されます:

論理型:

1. パズルクラス: パズルの記述に使用 2. 設定クラス: 設定変数の保存

対話型: 3. ゲームメニューウィンドウ: メニューオプションの実行

4 .ゲーム実行ウィンドウ: ゲームのメインインターフェイス

1. 難易度や画像などの設定は、ゲームメニューから操作できます。 2. 実行中のウィンドウは、ゲーム構成にアクセスして取得し、対応する構築パズル オブジェクトを使用できます。

3. ユーザーは実行中のウィンドウを通じて対話し、間接的にパズルオブジェクトに move メソッドを呼び出してパターンメソッドを取得させます

コードを読んだ学生の皆さん、一番問題で無理があると思うのは、パズルクラスに難易度列挙型が書かれていることです。構成クラスか別のクラスに書くべきで、読者は自分で変更できます。


 public enum Diff //游戏难度
 {
  simple,//简单
  ordinary,//普通
  difficulty//困难
 }

設定クラスはデータストレージのようなものであり、パズルクラスは論理処理として使用され、メニューと実行ウィンドウは対話のためのプレゼンテーションとして使用されると考えることができますが、この設計はあまり良くないことは認めます。合理的だが、問題の規模が十分でない場合 設計する際、考えすぎてプログラムが肥大化してしまわないか?ある程度のことはあると思うんですが、よく分かりませんが、このプログラムに関しては、とにかく実装して、デザイン(ルーチン型)にこだわったほうが得が上回ることもあると思います。 (個人的な未熟な意見)

(3) コード実装:

説明: このブロックは、Puzzle クラスとゲーム実行クラス間の特定の実装とエンティティ通信の記述に焦点を当てています:

パズルの

構造メソッド :

1. 割り当て:

public Puzzle(Image Img, int

Width, Diff GameDif)

// パズルの画像、幅 (説明: 正方形の辺の長さ、単位はピクセル、名前があいまいです、ごめんなさい)、ゲームの難易度です

ゲームの難易度は、分割の度合いを決定します。たとえば、simple は 3 に対応します。行 3 列、通常は 5 行 5 列、難しい場合は 9 行 9 列に対応します

 switch(this._gameDif)
  {
  case Diff.simple:    //简单则单元格数组保存为3*3的二维数组
   this.N = 3;
   node=new Node[3,3];
   break;
  case Diff.ordinary:   //一般则为5*5
   this.N = 5;
   node = new Node[5, 5];
   break;
  case Diff.difficulty:  //困难则为9*9
   this.N = 9;
   node = new Node[9, 9];
   break;
  }

2. 画像を分割します。実際、cell 配列に値を割り当てるプロセスは、2 層の for ループ を使用して 2 次元配列を走査し、次に Sequential assign Number node[x,y].Num; を押すことです。次に、ユニットの小さな画像であるnode[x,y].Imgに値を割り当てます。割り当て方法は、C#の画像クラスライブラリメソッドのスクリーンショットを書き込むことです。このメソッドを使用して、対応するサイズの小さな画像をインターセプトします。全体像内の対応する位置に対応し、node[x,y].Img に保存します。

width/N とは何ですか?辺の長さを行数で割ったものが間隔であり、間隔が各ユニットの辺の長さになります。すると、開始座標 (X, Y) は、数単位後の私の位置


が次のようになります: (x, y)

=

(単位辺の長さ * 開始 X 軸からの距離 単位数、単位辺の長さ * Y 軸から開始点までの単位数); この種の問題については、読者がもっと図を描けば自然に理解できると思います。

public Image CaptureImage(Image fromImage, int width, int height

, int space 白ですよね?デフォルトの位置は、node[N-1, N-1] です。

は白い絵に書き込まれ、周囲のエッジは他の人によって発見され、より目立つようになります。以前の他のユニットにも境界線を描きましたが、パズルの装飾的な品質を区別するために、境界線は白でした。このコードは紹介されません。

3. 画像をスクランブルする:

は実際には 2 次元配列をスクランブルするために、いくつかの並べ替えおよびスクランブル方法を使用できますが、注意してください。すべての混乱を回復できるわけではありません。 では、どうすればそれを実現できるのでしょうか?この方法は理解するのが非常に簡単です。つまり、ゲーム開始前に、ルールで指定された歩行方法に従って、完全かつ順序付けられたユニットを不規則かつ多数回コンピュータに歩行させます。つまり、この道なら絶対に戻れる!

具体的な破壊方法については後ほど説明しますので、まず理解してください。

移動方法(移動):

パズルゲームにおける正方形の移動は、実際には隣接する2つのユニットの交換であり、これら2つのユニットの間には白いユニット(つまり、上記のノード[ N- 1, N-1] ユニット、その番号は N*N-1 です。自分で計算することをお勧めします)

したがって、私たちの判断条件は、ブロックを上下 4 方向に移動すると、左右に隣接する白いユニット、つまりユニット番号 N*N-1 があれば、それと交換します。これは基本的なロジックですが、

制約

条件は含まれていません。たとえば、ユニットがnode[0,0]の場合、境界外のデータにはアクセスできません。上記にアクセスすると、Node[-1,0] Node[0,-1] が範囲外となり例外が発生するため、右側のデータがアクセスされます

移動が成功すると TRUE が返されます。 .

移動が失敗した場合は、

が返されます。
/// <summary>
 /// 移动坐标(x,y)拼图单元
 /// </summary>
 /// <param name="x">拼图单元x坐标</param>
 /// <param name="y">拼图单元y坐标</param>
 public bool Move(int x,int y)
 {
  //MessageBox.Show(" " + node[2, 2].Num);
  if (x + 1 != N && node[x + 1, y].Num == N * N - 1)
  {
  Swap(new Point(x + 1, y), new Point(x, y));
  return true;
  }
  if (y + 1 != N && node[x, y + 1].Num == N * N - 1)
  {
  Swap(new Point(x, y + 1), new Point(x, y));
  return true;
  }  
  if (x - 1 != -1 && node[x - 1, y].Num == N * N - 1)
  {
  Swap(new Point(x - 1, y), new Point(x, y));
  return true;
  } 
  if (y - 1 != -1 && node[x, y - 1].Num == N * N - 1)
  {
  Swap(new Point(x, y - 1), new Point(x, y));
  return true;
  }
  return false;
  
 }

交换方法(Swap):

交换数组中两个元素的位置,该方法不应该被类外访问,顾设置为private私有权限


 //交换两个单元格
 private void Swap(Point a, Point b)
 {
  Node temp = new Node();
  temp = this.node[a.X, a.Y];
  this.node[a.X, a.Y] = this.node[b.X, b.Y];
  this.node[b.X, b.Y] = temp;
 }

打乱方法:

前面提到,其实就是让电脑帮着乱走一通,说白了就是大量的调用Move(int X,int y)方法,也就是对空白位置的上下左右四个相邻的方块中随机抽取一个,并把它的坐标传递给Move使其进行移动,同样要进行越界考虑,这样的操作大量重复!代码自己看吧 ,利用随机数。


/// <summary>
 /// 打乱拼图
 /// </summary>
 public void Upset()
 {
  int sum = 100000;
  if (this._gameDif == Diff.simple) sum = 10000;
  //if (this._gameDif == Diff.ordinary) sum = 100000;
  Random ran = new Random();
  for (int i = 0, x = N - 1, y = N - 1; i < sum; i++)
  {
  long tick = DateTime.Now.Ticks;
  ran = new Random((int)(tick & 0xffffffffL) | (int)(tick >> 32)|ran.Next());
  switch (ran.Next(0, 4))
  {
   case 0:
   if (x + 1 != N)
   {
    Move(x + 1, y);
    x = x + 1;
   }
    
   break;
   case 1:
   if (y + 1 != N)
   {
    Move(x, y + 1);
    y = y + 1;
   } 
   break;
   case 2:
   if (x - 1 != -1)
   {
    Move(x - 1, y);
    x = x - 1;
   } 
   break;
   case 3:
   if (y - 1 != -1)
   {
    Move(x, y - 1);
    y = y - 1;
   }
   break;
  }

  }
 }

返回图片的方法:

当时怎么起了个这样的鬼名字。。。DisPlay。。。

这个方法与分割方法刚好相背,这个方法其实就是遍历数组,并将其进行组合,组合的方法很简单,就是将他们一个一个的按位置画在一张与原图相等大小的空白图纸上!最后提交图纸,也就是return一个Image;


 public Image Display()
 {
  Bitmap bitmap = new Bitmap(this.Width, this.Width);
  //创建作图区域 
  Graphics newGra = Graphics.FromImage(bitmap);
  for (int x = 0; x < this.N; x++)
  for (int y = 0; y < this.N; y++)
   newGra.DrawImage(node[x, y].Img, new Point(x * this.Width / this.N, y * this.Width / this.N));
  return bitmap;
 }

同样利用的是DrawImage方法,知道如何分割,这个应该很容易理解,自己算一算,在纸上比划比划就明白了;

判断方法:

该方法很容易理解,就是按序按序!遍历所有单元,如果他们的结果中有一个单元的编号

node[x, y].Num 不等于遍历的序号,那么说明,该单元不在原有位置上,即整个图片还没有完成,我们就可以直接返回假值false
如果所有遍历结果都正确,我们可认为,图片已复原,此时返回真值true


 public bool Judge()
 {
  int count=0;
  for (int x = 0; x < this.N; x++)
  {
  for (int y = 0; y < this.N; y++)
  {
   if (this.node[x, y].Num != count)
   return false;
   count++;
  }
  }
  return true;
 }

游戏运行窗口:即游戏玩耍时用于交互的窗口

这里只讲一个方法:即当接受用户鼠标点击事件时我们应该怎么处理并作出什么样反应

其实说白了就这句难懂:

puzzle.Move(e.X / (puzzle.Width / puzzle.N), e.Y / (puzzle.Width / puzzle.N))

调用了移动方法,移动方块

横坐标为:e.X / (puzzle.Width / puzzle.N)
纵坐标为:e.Y / (puzzle.Width / puzzle.N)

我们编程中的整数除法和数学里的除法是不一样的!比如10/4数学上等于2余2或者2.5,计算机里直接就是等于2了,只取整数部分

行数=行坐标 / 方块边长

列数=列坐标 / 方块边长

我们看P1,P2这两点

P1:40/30*30=1
P2:50/30*30=1

我们会发现同在一个单元格中,无论点击哪个位置,通过这个算法都能转化为
同一个坐标。

(e.x,e.y)为鼠标点击事件点击坐标


 private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
 {
  if (puzzle.Move(e.X / (puzzle.Width / puzzle.N), e.Y / (puzzle.Width / puzzle.N)))
  {
  Num++;
  pictureBox1.Image = puzzle.Display();
  if (puzzle.Judge())
  { 
   if (MessageBox.Show("恭喜过关", "是否重新玩一把", MessageBoxButtons.OKCancel) == DialogResult.OK)
   {
   Num = 0;
   puzzle.Upset();
   pictureBox1.Image = puzzle.Display();
   
   }
   else
   {
   Num = 0;
   closefather();
   this.Close();
   }

  }

  }
  NumLabel.Text = Num.ToString();
 }

好,那么大体的逻辑,程序中最需要思考的算法已经讲完了,还有不太懂的地方,欢迎交流~么么哒~

加了点小功能 音乐历史成绩

以上がC# でジグソーパズルを作成するためのグラフィック コードとテキスト コードの共有 (パート 2)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
C#と.NETランタイム:それらがどのように連携するかC#と.NETランタイム:それらがどのように連携するかApr 19, 2025 am 12:04 AM

C#と.NETランタイムは密接に連携して、開発者に効率的で強力なプラットフォームの開発機能に力を与えます。 1)C#は、.NETフレームワークとシームレスに統合するように設計されたタイプセーフおよびオブジェクト指向のプログラミング言語です。 2).NETランタイムは、C#コードの実行を管理し、ガベージコレクション、タイプの安全性、その他のサービスを提供し、効率的でクロスプラットフォームの操作を保証します。

C#.NET開発:始めるための初心者向けガイドC#.NET開発:始めるための初心者向けガイドApr 18, 2025 am 12:17 AM

C#.NET開発を開始するには、次のことが必要です。1。C#の基本的な知識と.NETフレームワークのコア概念を理解する。 2。変数、データ型、制御構造、関数、クラスの基本概念をマスターします。 3。LINQや非同期プログラミングなど、C#の高度な機能を学習します。 4.一般的なエラーのためのデバッグテクニックとパフォーマンス最適化方法に精通してください。これらの手順を使用すると、C#.NETの世界に徐々に浸透し、効率的なアプリケーションを書き込むことができます。

C#と.NET:2つの関係を理解し​​ますC#と.NET:2つの関係を理解し​​ますApr 17, 2025 am 12:07 AM

C#と.NETの関係は切り離せませんが、同じものではありません。 C#はプログラミング言語であり、.NETは開発プ​​ラットフォームです。 C#は、コードの書き込み、.NETの中間言語(IL)にコンパイルされ、.NET Runtime(CLR)によって実行されるために使用されます。

c#.netの継続的な関連性:現在の使用法を見るc#.netの継続的な関連性:現在の使用法を見るApr 16, 2025 am 12:07 AM

C#.NETは、複数のアプリケーション開発をサポートする強力なツールとライブラリを提供するため、依然として重要です。 1)C#は.NETフレームワークを組み合わせて、開発を効率的かつ便利にします。 2)C#のタイプの安全性とゴミ収集メカニズムは、その利点を高めます。 3).NETは、クロスプラットフォームの実行環境とリッチAPIを提供し、開発の柔軟性を向上させます。

Webからデスクトップまで:C#.NETの汎用性Webからデスクトップまで:C#.NETの汎用性Apr 15, 2025 am 12:07 AM

c#.netisversatileforbothwebanddesktopdevelopment.1)forweb、useasp.netfordynamicapplications.2)fordesktop、equindowsorwpfforrichinterfaces.3)usexamarinforcross-platformdeveliment、enabling deshacrosswindows、

c#.net and the Future:新しいテクノロジーへの適応c#.net and the Future:新しいテクノロジーへの適応Apr 14, 2025 am 12:06 AM

C#と.NETは、継続的な更新と最適化を通じて、新しいテクノロジーのニーズに適応します。 1)C#9.0および.NET5は、レコードタイプとパフォーマンスの最適化を導入します。 2).Netcoreは、クラウドネイティブおよびコンテナ化されたサポートを強化します。 3)ASP.Netcoreは、最新のWebテクノロジーと統合されています。 4)ML.NETは、機械学習と人工知能をサポートしています。 5)非同期プログラミングとベストプラクティスはパフォーマンスを改善します。

c#.netはあなたにぴったりですか?その適用性の評価c#.netはあなたにぴったりですか?その適用性の評価Apr 13, 2025 am 12:03 AM

c#.netissuitableforenterprise-levelApplicationsとsystemduetoitsSystemdutyping、richlibraries、androbustperformance.

.NET内のC#コード:プログラミングプロセスの調査.NET内のC#コード:プログラミングプロセスの調査Apr 12, 2025 am 12:02 AM

.NETでのC#のプログラミングプロセスには、次の手順が含まれます。1)C#コードの作成、2)中間言語(IL)にコンパイルし、3).NETランタイム(CLR)によって実行される。 .NETのC#の利点は、デスクトップアプリケーションからWebサービスまでのさまざまな開発シナリオに適した、最新の構文、強力なタイプシステム、および.NETフレームワークとの緊密な統合です。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター