初心者が15パズル作成するのは、難しいでしょうか。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
taka_taka

初心者が15パズル作成するのは、難しいでしょうか。

#1

投稿記事 by taka_taka » 11年前

新ゲームプログラミングの館を、再度自分なりにやりまして、
リファレンスの使い方や関数の意味の理解を深めました。

次に簡単なゲームを作りたいと思い、15パズルはどうだろうかと
考えました。

最初、15パズルの表示をしたいと思いやりましたが、
15個表示ならともかく、16分割した一つずつをウィンドウに表示する方法は?
と混乱してしまいました。

その段階で、設計が出来ないと無理かもしれないとも感じました。
パズルを表示させたとき、キー入力の指定はどう受けるのか、
座標指定なのかなどです。
例えば、Puzzle.cpp、Puzzle.h、Keyboard.cpp、Keyboard.h、main.cppのように
全体の構成や関係が決められないと、そもそも細かい処理もいいのか悪いか判断つかないような
感じを受けました。

そもそも15パズルは初心者には難しいのでしょうか。
難しくなければ、初心者が1から作るときに、最初に考えるべきところなどは
ありますでしょうか。

taka_taka

わかりずらくてすいません。

#2

投稿記事 by taka_taka » 11年前

パズルを分割して、表示する方法は知っていますが、
ウィンドウいっぱい、もしくはウィンドウの一部どちらに表示がいいのか。

全体よりも、そもそも一つずつの画像を利用するのがいいのかなど、
その後の処理を想定しないと、決められそうもないことが多いと感じました。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#3

投稿記事 by h2so5 » 11年前

taka_taka さんが書きました: そもそも15パズルは初心者には難しいのでしょうか。
難しくなければ、初心者が1から作るときに、最初に考えるべきところなどは
ありますでしょうか。
コーディングの難易度としては高くないと思います。
考えるだけじゃなくて実際にコードを書いてください、そうしないと進みません。

パズルを分割して、表示する方法は知っているならコードを書いてください。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: わかりずらくてすいません。

#4

投稿記事 by softya(ソフト屋) » 11年前

taka_taka さんが書きました:パズルを分割して、表示する方法は知っていますが、
ウィンドウいっぱい、もしくはウィンドウの一部どちらに表示がいいのか。
それはレイアウトとかデザインの問題ですね。
プログラミングとは無関係です。
最初から完全を目指すのではなく、とりあえず始めてみたらどうでしょうか。
taka_taka さんが書きました: 全体よりも、そもそも一つずつの画像を利用するのがいいのかなど、
その後の処理を想定しないと、決められそうもないことが多いと感じました。
どちらでも出来ますが、やってみないと分からないと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka

15パズルを表示だけするプログラムを書きましたが、エラーがでました。

#5

投稿記事 by taka_taka » 11年前

左上から右下へ、1から15までの一つの図を、16分割して表示させていくコードの途中です。
とりあえず、分割して、キーを押したりして、順に1,2,3、、、と表示させたい意図です。
まだ、コードも途中で、differ(完成との比較)や移動の関数は書いていません。
エラーがでてしまい、どうしてもエラーが解決しません。

1.main.cppのPuzzle_Initialize(&m_Puzzle, 0, 0, GrHandle)で、
 GrHandle int [16] を構造体のint * imgに渡したいですが、エラーがでます。

2.Puzzle.cpp
void Puzzle_Finalize(Puzzle_t Puzzle){
DrawGraph( Puzzle.Image );
}
で、構造体のint *Image;の処理が出来ません。
それに関連してなのかわかりませんが、三つのエラーが出ます。

趣旨がずれていますが、アドバイスをいただけると助かります。
エラーの行数は2行くらいずれていますが、申し訳ございません。

・puzzle.cpp(34) : error C2144: 構文エラー : 'void' は ';' によって先行されなければなりません。

・puzzle.cpp(34) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません

・puzzle.cpp(35) : error C2660: 'DxLib::DrawGraph' : 関数に 1 個の引数を指定できません。

main.cpp
main.cpp(29) : error C2664: 'Puzzle_Initialize' : 4 番目の引数を 'int [16]' から 'int' に変換できません。(新しい機能 ; ヘルプを参照)  この変換が可能なコンテキストはありません。

Puzzle.cpp
puzzle.cpp(34) : error C2144: 構文エラー : 'void' は ';' によって先行されなければなりません。

puzzle.cpp(34) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません

puzzle.cpp(35) : error C2660: 'DxLib::DrawGraph' : 関数に 1 個の引数を指定できません。

コード:

//main.cpp 
#include "DxLib.h"
#include "Puzzle.h"
#include "Keyboard.h"

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

	int GrHandle[16];
	int i = -1, j = -1;
	int m_ImgPuzzle;

	Puzzle_t m_Puzzle;
	
	ChangeWindowMode(true) ; 

	if (DxLib_Init() == -1)
	{
		DrawFormatString(0, 0, GetColor(0, 0, 255), "DxLib_Init err");
	}
	
	m_ImgPuzzle = LoadDivGraph("C:/Documents and Settings/All Users/Documents/My Pictures/Sample Pictures/16puzzle01.png", 16, 4, 4, 100, 100, GrHandle);

	if (m_ImgPuzzle == -1)
	{
		DrawFormatString(0, 0, GetColor(0, 0, 255), "LoadDivGraph err\n");
	}

	//DrawGraph( 0, 0, GrHandle[1], TRUE );
	
	Puzzle_Initialize(&m_Puzzle, 0, 0, GrHandle);

	while(ProcessMessage() != -1)
	{
		Keyboard_Update();    //キーボードの更新

		Puzzle_Update(&m_Puzzle, i, j);
		
		Puzzle_Draw(m_Puzzle, i);
	}

	WaitKey();

	if (DxLib_End() == -1)
	{
		DrawFormatString(0, 0, GetColor(0, 0, 255), "DxLib_End err");
	}

	return 0;

}
 

コード:

 
//Puzzle.cpp
#include "DxLib.h"
#include "Keyboard.h"
#include "Puzzle.h"

// 初期化をする
void Puzzle_Initialize(Puzzle_t *Puzzle, int x, int y, int img[]){
	Puzzle->Image = img;
	Puzzle->x = x;
	Puzzle->y = y;
}

// 動きを計算する
void Puzzle_Update(Puzzle_t *Puzzle, int i, int j){
	if(Keyboard_Get(KEY_INPUT_UP) > 0 ){
		i++;
		if (i%4 == 0) j++;
		Puzzle->x = 100 * (i % 4);
		Puzzle->y = 100 * j;
	}
	if(Keyboard_Get( KEY_INPUT_DOWN ) > 0 ){
		i--;
		if (i%4 == 0) j--;
		Puzzle->x = 100 * (i % 4);
		Puzzle->y = 100 * j;
	}
}

// 描画する
void Puzzle_Draw(Puzzle_t Puzzle, int i){
	DrawGraph( Puzzle.x, Puzzle.y, Puzzle.Image[i], TRUE );
}

 終了処理をする
void Puzzle_Finalize(Puzzle_t Puzzle){
        DrawGraph( Puzzle.Image );
}

コード:

 
//Puzzle.h
#ifndef DEF_PUZZLE_H //二重include防止

#define DEF_PUZZLE_H

typedef struct{
	int *Image;
	int x;
	int y;
} Puzzle_t;

// 初期化をする
void Puzzle_Initialize( Puzzle_t *Puzzle, int x, int y, int img);

// 動きを計算する
void Puzzle_Update(Puzzle_t *Puzzle, int i, int j);

// 結果を完成と比較する
void Puzzle_Differ( Puzzle_t *Puzzle );

// 描画する
void Puzzle_Draw( Puzzle_t Puzzle, int i);

// 終了処理をする
void Puzzle_Finalize( Puzzle_t Puzzle );

#endif 
 

コード:

 
//Keyboard.cpp
#include "DxLib.h"

static int m_Key[256];  // キーの入力状態格納用変数

// キーの入力状態更新
void Keyboard_Update(){
        char tmpKey[256];             // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey );  // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        m_Key[i]++;   // 加算
                } else {              // 押されていなければ
                        m_Key[i] = 0; // 0にする
                }
        }
}

// KeyCodeのキーの入力状態を取得する
int Keyboard_Get( int KeyCode ){
        return m_Key[ KeyCode ]; // KeyCodeの入力状態を返す
} 
 

コード:

 
//Keyboard.h
#ifndef DEF_KEYBOARD_H //二重include防止

#define DEF_KEYBOARD_H

// キーの入力状態を更新する
void Keyboard_Update();

// 引数のキーコードのキーの入力状態を返す
int Keyboard_Get( int KeyCode );

#endif 
 

taka_taka

i, j の扱いがおかしいのはすいません。

#6

投稿記事 by taka_taka » 11年前

出来るかどうかわかりませんが、Puzzleの構造体に入れようと思っています。

最初、ヘッダーファイルで分割しないコードは下記です。
これでは、表示自体はできてました。

コード:

#include "DxLib.h"
#include "Puzzle.h"

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

	int GrHandle[16];
	int i = -1, j = -1;
	int check;

	Puzzle_t m_Puzzle;
	
	ChangeWindowMode(true) ; 

	if (DxLib_Init() == -1)
	{
		DrawFormatString(0, 0, GetColor(0, 0, 255), "DxLib_Init err");
	}
	
	check = LoadDivGraph("C:/Documents and Settings/All Users/Documents/My Pictures/Sample Pictures/16puzzle01.png", 16, 4, 4, 100, 100, GrHandle);

	if (check == -1)
	{
		DrawFormatString(0, 0, GetColor(0, 0, 255), "LoadDivGraph err\n");
	}
		
	while(ProcessMessage() != -1)
	{
		i++ ;
		if(i == 15) break;
		if (i%4 == 0) j++;

		DrawGraph( 0 + 100 * (i % 4), 0 + 100 * j, GrHandle[i] , FALSE);

		if( ProcessMessage() == -1 )
		{
			break ;
		}
	}

	WaitKey();

	if (DxLib_End() == -1)
	{
		DrawFormatString(0, 0, GetColor(0, 0, 255), "DxLib_End err");
	}

	return 0;

}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#7

投稿記事 by softya(ソフト屋) » 11年前

まず、書いてはいけない4つの処理 に該当してしまっています。
http://dixq.net/g/h_11.html
ファイル分割の前に、そこを直しましょう。

それと
2.9 全てのキーの入力状態を取得する
http://dixq.net/g/02_09.html
を原型にしたほうが良いでしょう。

まず、ここからです。

[補足]
DxLib_End()はエラーチェックしなくて良いです。
エラーチェックしても、その方法ではエラー表示できない可能性が高いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

nil
記事: 428
登録日時: 12年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#8

投稿記事 by nil » 11年前

各Finalize関数でDrawGraphをしているのは何故でしょうか?
……というかそもそもFinalize関数は呼び出されていないようですが。
エラーチェックですが、
DrawFormatStringを使うのはよしたほうが良いでしょう。

何故ならば、
例えばDxLib_Initに失敗した場合、当然ウィンドウは作られず、DrawFormatStringをしても描画はされないからです。
それに、DrawFormatStringではClearDrawScreenが呼ばれた時に消えてしまいますし。
……個人的な好き嫌いでは、書式を指定しないときはDrawStringを使うことをおすすめしたいです。可変長引数は厄介ですから。

僕の場合はエラーが発生すると、MessageBoxAを呼び出し、それを使ってエラーを知らせるようにしています。
また、DxLib_Initが失敗した場合は、すぐさまプログラムを終了したほうが良いです。
ゴースト化の原因となったりすることがあります。

次に、絶対パスを使ってファイルをロードするのは止めたほうが良いです。
練習段階ならまだいいですが、本格的にプログラムを組むのなら(特別な処理をしようと思わない限り)相対パスを使用しましょう。

最後に、これは別に個人的に気になっただけなのですが、
m_Puzzleという変数名、m_というのは、一般的にはクラスのメンバ変数に付けられることが多い接頭辞であり、ただの変数にこれをつけるのは
他人からしても混乱の原因となるため、避けたほうが良いかと思われます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#9

投稿記事 by softya(ソフト屋) » 11年前

オフトピック
m_と言うのはゲームプログラミングの館でDixqさんがやっていたような・・・。
「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/d_03.html
たぶん、c++的な書き方の準備という意味でやっているのでは?
まぁ、涼雅さんの言われるようにエラー表示はDrawFormatStringを使わずMessageBoxAですぐ終了が良いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

15パズルを表示する処理が出来ません。

#10

投稿記事 by taka_taka » 11年前

色々な方々の意見を参考に作り直しました。
といっても、MessageBoxを使った点が一番の変更点です。

16分割した後、1から順に並べて、全体を表示させたいのですが、
一つ表示するごとに消えてしまい、位置をずらして、一つずつ描図することしかできません。
メインループとは別ループを作り、その中で処理するのがよいでしょうか。

コード:

//main.cpp
#include "DxLib.h"
#include "Keyboard.h"
#include "Puzzle.h"

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

	int GrHandle[16];
	int i = -1, j = -1;
	int m_ImgPuzzle;
	int flag;

	Puzzle_t m_Puzzle;

	ChangeWindowMode(true) ; 

	if (DxLib_Init() != 0)
	{
		flag = MessageBox(
                NULL ,
                TEXT("DxLib_Init() err") ,
                TEXT("Err") , 
                MB_OK);
		if (flag == IDOK) return -1;
	}

	if (SetDrawScreen(DX_SCREEN_BACK) != 0)
	{
		flag = MessageBox(
				NULL ,
				TEXT("SetDrawScreen(DX_SCREEN_BACK) err") ,
				TEXT("Err") , 
				MB_OK);
					
		if (flag == IDOK){
			DxLib_End();
			return -1;
		}
	}

	m_ImgPuzzle = LoadDivGraph("C:/Documents and Settings/All Users/Documents/My Pictures/Sample Pictures/16puzzle01.png", 16, 4, 4, 100, 100, GrHandle);

	if (m_ImgPuzzle != 0)
	{
		flag = MessageBox(
				NULL ,
				TEXT("LoadDivGraph err") ,
				TEXT("Err") , 
				MB_OK);
					
		if (flag == IDOK){
			DxLib_End();
			return -1;
		}
	}

	Puzzle_Initialize(&m_Puzzle, 0, 0, GrHandle);
	
	while( 1 ){
		if( ScreenFlip() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("LoadDivGraph err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}
		if( ProcessMessage() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ProcessMessage err(End)") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}
		if( ClearDrawScreen() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ProcessMessage err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}

		if( Keyboard_Update() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("Keyboard_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}	
			if (i == 16) break;

			;    //キーボードの更新

			//DrawFormatString(0, 0, GetColor(0, 0, 255), "%d" ,i);
		
			//DrawGraph( 0, 0, GrHandle[6], TRUE );

			Puzzle_Update(&m_Puzzle, &i, &j);
			Puzzle_Draw(m_Puzzle, i);
			WaitKey();	
	}

	Puzzle_Finalize(m_Puzzle);
	
	if (DxLib_End() != 0)
	{
		DrawFormatString(0, 0, GetColor(0, 0, 255), "DxLib_End err");
		return 0;
	}

	return 0;

}

コード:

 
//Puzzle.cpp
#include "DxLib.h"
#include "Keyboard.h"
#include "Puzzle.h"

// 初期化をする
void Puzzle_Initialize(Puzzle_t *Puzzle, int x, int y, int img[]){
	Puzzle->Image = img;
	Puzzle->x = x;
	Puzzle->y = y;
}

// 動きを計算する
void Puzzle_Update(Puzzle_t *Puzzle, int *i, int *j){
	if(Keyboard_Get(KEY_INPUT_UP) > 0 ){
		*i = *i + 1;
		if ((*i)%4 == 0) *j = *j+ 1;
		Puzzle->x = 100 * ((*i) % 4);
		Puzzle->y = 100 * (*j);
	}
	if(Keyboard_Get( KEY_INPUT_DOWN ) > 0 ){
		*i = *i - 1;
		if ((*i)%4 == 0) *j--;
		Puzzle->x = 100 * ((*i) % 4);
		Puzzle->y = 100 * (*j);
	}
}

// 描画する
void Puzzle_Draw(Puzzle_t Puzzle, int i){
	DrawGraph( Puzzle.x, Puzzle.y, Puzzle.Image[i], FALSE);
}

//終了処理をする
void Puzzle_Finalize(Puzzle_t Puzzle){
	
	int i;
	
	for (i = 0; i < sizeof(Puzzle.Image)/sizeof(Puzzle.Image[0]); i++)
	{
		DeleteGraph(Puzzle.Image[i]);
	}
}

コード:

//Puzzle.h
#ifndef DEF_PUZZLE_H //二重include防止

#define DEF_PUZZLE_H

typedef struct{
	int *Image;
	int x;
	int y;
} Puzzle_t;

// 初期化をする
void Puzzle_Initialize( Puzzle_t *Puzzle, int x, int y, int img[]);

// 動きを計算する
void Puzzle_Update(Puzzle_t *Puzzle, int *i, int *j);

// 結果を完成と比較する
void Puzzle_Differ( Puzzle_t *Puzzle );

// 描画する
void Puzzle_Draw( Puzzle_t Puzzle, int i);

// 終了処理をする
void Puzzle_Finalize(Puzzle_t Puzzle);

#endif 

コード:

//Keyboard.cpp
#include "DxLib.h"

static int m_Key[256];  // キーの入力状態格納用変数

// キーの入力状態更新
int Keyboard_Update(){
        char tmpKey[256];             // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey );  // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        m_Key[i]++;   // 加算
                } else {              // 押されていなければ
                        m_Key[i] = 0; // 0にする
                }
        }
        
		return 0;
}

// KeyCodeのキーの入力状態を取得する
int Keyboard_Get( int KeyCode ){
        return m_Key[ KeyCode ]; // KeyCodeの入力状態を返す
} 

コード:

//Keyboard.h
#ifndef DEF_KEYBOARD_H //二重include防止

#define DEF_KEYBOARD_H

// キーの入力状態を更新する
int Keyboard_Update();

// 引数のキーコードのキーの入力状態を返す
int Keyboard_Get( int KeyCode );

#endif 

taka_taka
記事: 79
登録日時: 11年前

説明不足ですいません。追加になります。

#11

投稿記事 by taka_taka » 11年前

main.cppのClearDrawScreenをコメントアウトすると、上を押し続けると、
パズルが埋まっていくといった意図した表示が出来ます。
しかし、ClearDrawScreenの位置は変えてもいいのか、判断つきません。
例えば、表示して、さらにこれからですが、変更処理、完成判断処理などを付け加えたときに、
最終処理でClearDrawScreenとするものでしょうか。

コード:

/*if( ClearDrawScreen() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ProcessMessage err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}
*/
あと、
1.DxLib_End()のエラー処理がまだ訂正していませんでした。すいません。

2.画像の相対パスも知識不足で、まだできていません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#12

投稿記事 by softya(ソフト屋) » 11年前

ごめんなさい過剰なエラーチェックでコードが凄く読みづらいです。
エラー内容はLog.txtに出るので表示しなくて良いですよ。
あとProcessMessageはエラー以外の意味もあるので!=0っチェックしてもダメです。
つまり、元のままがシンプルで良いんです。
過ぎたるは及ばざるが如しです。

それ以外に気になる所。
・インデントが狂っていますね。
・無駄にポインタを使用している。
・ロードは初期化でやるべきだと思います。
・変数名が意味と食い違っている。m_ImgPuzzleなど。
・i,j,x,yだと意味不明な所があります。ちゃんと名前を付けられる所は付けましょう。安易な名前は避けましょう。
・ WaitKey(); は禁止。毎フレームパズルピースは全てを描画しましょう。
Puzzle_t;やらPuzzle_InitializeやらPuzzle_UpdateやらPuzzle_Drawを組み直す必要があります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

ありがとうございます。

#13

投稿記事 by taka_taka » 11年前

ご指摘は、参考になります。
直してみたいと思いますが、出来るかどうか不安です。
とりあえず、やってみます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#14

投稿記事 by softya(ソフト屋) » 11年前

関数やファイル分けして綺麗にする前にmainファイルだけで動くものを組んだほうが良いと思います。
15パズルを組むと言う事とファイル分割して綺麗に組むといいう2つにいっぺんにチャレンジしているので難易度が上がっています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

どりあえず、表示までは出来ました。

#15

投稿記事 by taka_taka » 11年前

mainにしたいのですが、仕方が分からないので、
分割のままですが、一応、15パズル表示までは出来ました。

もし、いきずまり、やりずらくなりましたら、mainだけで書き直して見ようと思います。
相当難しいだろうことは覚悟していますので、迷います。

今は、移動処理を考えていますが、画像分割をしたものを、
ハンドルで表示させるのは分かります。
移動させるときは、マウスクリックで周囲が開いていたら、
動くようにしたいです。

普通、マウスの位置情報x,y の処理は、座標領域
0<x<100, 0<y<100が1
100<x<200, 0<y<100が2
・・・・
といった感じで処理するイメージでしょうか。
多分、100×100が一ブロックなので、100を定数BLOCK_SIZEなどにするといいのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#16

投稿記事 by softya(ソフト屋) » 11年前

>もし、いきずまり、やりずらくなりましたら、mainだけで書き直して見ようと思います。
>相当難しいだろうことは覚悟していますので、迷います。

いや、mainだけで書くほうが簡単でファイル分割するほうが難しいというか、ちゃんと書かないと意味が無いと言うかです。
ファイル分割がちゃんと出来る人は、main で書くことは造作も無いって事なんですけどね。

それと最新のコードを見せてもらえますか?

>今は、移動処理を考えていますが、画像分割をしたものを、
>ハンドルで表示させるのは分かります。
>移動させるときは、マウスクリックで周囲が開いていたら、
>動くようにしたいです。

>多分、100×100が一ブロックなので、100を定数BLOCK_SIZEなどにするといいのでしょうか。

まず、マウスでピース選択を出来るようにしましょう。
1つ100ピクセル(多分とは?)ならBLOCK_SIZEを定数として計算だけでピース番号が求められるはずです。
ただ、その前に乱数でピースの入れ替えって終わっているんでしょうか?
前のデータ構造だと、それが難しい設計でしたが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

コードですが、見ずらくて申し訳ありません。

#17

投稿記事 by taka_taka » 11年前

エラー処理だけは、まだ館のサンプルのように直していません。
忘れないように、慣れるまで、逆にこうしている感じでもあります。
MesageBoxの書き方もみずらくてすいません。

あと、素材が1から16までの数なので、表示は15までにしてあります。
素材を1から15にして、残りがブラックボックスという画像を16分割して
使用しようかと考えています。

ただ、並び替え処理が出来ていないので、そちらを先にしようかと思いました。
その後、マウスの選択と、移動、比較などを作っていきます。

キーボードとアップデイトの処理は、コメントアウトしてあります。

コード:

//main.cpp
#include "DxLib.h"
#include "Keyboard.h"
#include "Puzzle.h"

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

	int flag;

	Puzzle_t m_Puzzle;

	ChangeWindowMode(true); 

	if (DxLib_Init() != 0)
	{
		flag = MessageBox(
                NULL ,
                TEXT("DxLib_Init() err") ,
                TEXT("Err") , 
                MB_OK);
		if (flag == IDOK) return -1;
	}

	if (SetDrawScreen(DX_SCREEN_BACK) != 0)
	{
		flag = MessageBox(
				NULL ,
				TEXT("SetDrawScreen(DX_SCREEN_BACK) err") ,
				TEXT("Err") , 
				MB_OK);
					
		if (flag == IDOK){
			DxLib_End();
			return -1;
		}
	}

	Puzzle_Initialize(&m_Puzzle);

	while( 1 ){
		if( ScreenFlip() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ScreenFlip err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}
		if( ProcessMessage() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ProcessMessage err(End)") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}
		if( ClearDrawScreen() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ClearDrawScreen err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}

/*		if( Keyboard_Update() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("Keyboard_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}	
*/		
			//Puzzle_Update(&m_Puzzle, &i, &j);
			Puzzle_Draw(m_Puzzle);
			WaitKey();	
	}

	Puzzle_Finalize(m_Puzzle);
	
	if (DxLib_End() != 0)
	{
		DrawFormatString(0, 0, GetColor(0, 0, 255), "DxLib_End err");
		return 0;
	}

	return 0;

}

コード:

//Puzzle.cpp
#include "DxLib.h"
#include "Keyboard.h"
#include "Puzzle.h"

#define SIZE 100

// 初期化をする
void Puzzle_Initialize(Puzzle_t *Puzzle){
	LoadDivGraph("C:/Documents and Settings/All Users/Documents/My Pictures/Sample Pictures/16puzzle01.png", 16, 4, 4, SIZE, SIZE, Puzzle->GrHandle);
}
// 動きを計算する
/*void Puzzle_Update(Puzzle_t *Puzzle, int *i, int *j){
	if(Keyboard_Get(KEY_INPUT_UP) > 0 ){
		*i = *i + 1;
		*j = (*i)/4;
		Puzzle->x = SIZE * ((*i) % 4);
		Puzzle->y = SIZE * (*j);
	}
	if(Keyboard_Get( KEY_INPUT_DOWN ) > 0 ){
		*i = *i - 1;
		*j = (*i)/4;
		Puzzle->x = SIZE * ((*i) % 4);
		Puzzle->y = SIZE * (*j);
	}
}*/

// 全体を描画する
void Puzzle_Draw(Puzzle_t Puzzle){
	int i;

	for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[0]) - 1; i++)
	{
		DrawGraph( SIZE * (i % 4), SIZE * (i/4), Puzzle.GrHandle[i], FALSE);
	}
}

//終了処理をする
void Puzzle_Finalize(Puzzle_t Puzzle){
	
	int i;
	
	for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[0]); i++)
	{
		DeleteGraph(Puzzle.GrHandle[i]);
	}
}

コード:

//Puzzle.h
#ifndef DEF_PUZZLE_H //二重include防止

#define DEF_PUZZLE_H

typedef struct{
	int GrHandle[16];
} Puzzle_t;

// 初期化をする
void Puzzle_Initialize(Puzzle_t *Puzzle);

// 動きを計算する
void Puzzle_Update(Puzzle_t *Puzzle, int *i, int *j);

// 結果を完成と比較する
void Puzzle_Differ( Puzzle_t *Puzzle );

// 描画する
void Puzzle_Draw( Puzzle_t Puzzle);

// 終了処理をする
void Puzzle_Finalize(Puzzle_t Puzzle);

#endif 

コード:

//Keyboard.cpp
#include "DxLib.h"

static int m_Key[256];  // キーの入力状態格納用変数

// キーの入力状態更新
int Keyboard_Update(){
        char tmpKey[256];             // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey );  // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        m_Key[i]++;   // 加算
                } else {              // 押されていなければ
                        m_Key[i] = 0; // 0にする
                }
        }
        
		return 0;
}

// KeyCodeのキーの入力状態を取得する
int Keyboard_Get( int KeyCode ){
        return m_Key[ KeyCode ]; // KeyCodeの入力状態を返す
} 

コード:

//Keyboard.h
#ifndef DEF_KEYBOARD_H //二重include防止

#define DEF_KEYBOARD_H

// キーの入力状態を更新する
int Keyboard_Update();

// 引数のキーコードのキーの入力状態を返す
int Keyboard_Get( int KeyCode );

#endif 

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#18

投稿記事 by softya(ソフト屋) » 11年前

マウスとか後々の処理が作れないので、WaitKey(); を止めてもらわないと非常にマズイですね。
キー入力オンリーなら辛うじて作れないわけではないですが、それでも気の利いたことが出来ないので私は変えることを提案します。

あとシャッフルは出来ていないのですね。
入れ替えとかのためにはピース位置を管理するデータ構造を持たないと行けないので、先にそれを作ってそのついでにシャッフルを搭載すべきでしょうね。
どうやってピース位置を管理するか考えてみてください。

それとPuzzle_t m_Puzzle;ですが、Puzzle.cppのファイルスコープのstatic変数で良いと思います。

15パズルは凝った演出をすると結構高難度なものになります。
何処らへんで止めるかは今のうちに考えておいてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

ご返信ありがとうございます。

#19

投稿記事 by taka_taka » 11年前

静止画で出し続ければいいと思っていましたが、WaitKey();は、消します。
この場合、表画面にして、消去して、裏画面描写して・・・
というくり返しの処理という理解で間違いないでしょうか。
基本だと思いますので、そうします。

シャッフルは、ハンドルのインデックス数の、1から16を格納する配列を用意して、
要素をシャッフルして、利用すればいいと思います。
精度を考えると、アルゴリズムは難しそうです。

最終的には、パズル内の並び替え操作で、
要素がswap等されて、要素が1から16に格納される場合に
完成と判定が出来そうです。
違うかもしれませんが。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ご返信ありがとうございます。

#20

投稿記事 by softya(ソフト屋) » 11年前

taka_taka さんが書きました:静止画で出し続ければいいと思っていましたが、WaitKey();は、消します。
この場合、表画面にして、消去して、裏画面描写して・・・
というくり返しの処理という理解で間違いないでしょうか。
基本だと思いますので、そうします。
表ではなく裏画面です。ゲームプログラミングの館の基本骨格も、そうなっているはずです。
と言うより、そのままコピペして使ってください。
taka_taka さんが書きました: シャッフルは、ハンドルのインデックス数の、1から16を格納する配列を用意して、
要素をシャッフルして、利用すればいいと思います。
精度を考えると、アルゴリズムは難しそうです。
画像配列の添字と考えると1から16ではなく0から15です。
それと1ピースは表示しないようにしないといけません。例えば15とか。これは表示時だけで良いです。
と言うことで0から15をランダムに入れ替えます。15は空白部分を示すことになります。
ただし、無作為にシャッフルすると15パズルが完成しないパターンが有るはずなので、15の上下左右の入れ替えをランダムの行うという面倒なことが必要です。
つまり、初期化で15パズルの操作をランダムに数十回行ってパズルの開始パターンを作成するのです。 → 回数は調整してください。

精度に関しては、さほど難しく考えずDXライブラリの乱数を使ってください。
「C言語~ゲームプログラミングの館~」
http://dixq.net/g/34.html
taka_taka さんが書きました: 最終的には、パズル内の並び替え操作で、
要素がswap等されて、要素が1から16に格納される場合に
完成と判定が出来そうです。
違うかもしれませんが。
完成は数値が順番に並んでいるかで判定できると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#21

投稿記事 by taka_taka » 11年前

入れ違いですいません。
0から15をシャッフルして、0から14までを表示に使う処理で書いてみましたが、
標準関数を使用してしまいました。
この書き方は、よくないのでしょうか。

>初期化で15パズルの操作をランダムに数十回行ってパズルの開始パターンを作成するのです。 → 回数は調整してください。

こことPuzzle_tのstatic化は、これから作成したいと思います。

コード:

//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Keyboard.h"
#include "Puzzle.h"

//インクルード_標準
#include <stdlib.h>
#include <time.h>

//マクロ
#define BLOCK_SIZE 100
#define HANDLE_SIZE 16

//グローバル変数
static int place[HANDLE_SIZE];  // ハンドル位置情報の格納用変数

//関数定義
void swap(int *a, int *b){
	
	int temp = *a;
	*a = *b;
	*b = temp;
}

// 初期化をする
void Puzzle_Initialize(Puzzle_t *Puzzle){
	
	int i;
	int a, b;

	for (i = 0; i < HANDLE_SIZE; i++)
	{
		place[i] = i;
	}

	srand((unsigned)time(NULL));
	
	for (i = HANDLE_SIZE - 1; i > 1; i--)
	{
		a = i;
		b = rand() % i;
		swap(&place[a], &place[b]);
	}

	LoadDivGraph("C:/Documents and Settings/All Users/Documents/My Pictures/Sample Pictures/16puzzle01.png", 16, 4, 4, BLOCK_SIZE, BLOCK_SIZE, Puzzle->GrHandle);
	
}
// 動きを計算する
/*void Puzzle_Update(Puzzle_t *Puzzle, int *i, int *j){
	if(Keyboard_Get(KEY_INPUT_UP) > 0 ){
		*i = *i + 1;
		*j = (*i)/4;
		Puzzle->x = SIZE * ((*i) % 4);
		Puzzle->y = SIZE * (*j);
	}
	if(Keyboard_Get( KEY_INPUT_DOWN ) > 0 ){
		*i = *i - 1;
		*j = (*i)/4;
		Puzzle->x = SIZE * ((*i) % 4);
		Puzzle->y = SIZE * (*j);
	}
}*/

// 全体を描画する
void Puzzle_Draw(Puzzle_t Puzzle){
	int i;

	for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[0]) - 1; i++)
	{
		DrawGraph( BLOCK_SIZE * (place[i] % 4), BLOCK_SIZE * (place[i]/4), Puzzle.GrHandle[i], FALSE);
	}
}

//終了処理をする
void Puzzle_Finalize(Puzzle_t Puzzle){
	
	int i;
	
	for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[0]); i++)
	{
		DeleteGraph(Puzzle.GrHandle[i]);
	}
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#22

投稿記事 by softya(ソフト屋) » 11年前

Puzzle_tにint place[HANDLE_SIZE]を含まないとせっかくの構造体が中途半端になりますね。
それと先に書いてますが、適当にランダムシャッフルすると解けないパズルができます。
あと、パズルピースの表示が15番目のピースを表示したら動くスペースがないですよ。

それとHANDLE_SIZE 16が名前的に意味が不明です。PAZZLE_PIECE_NUM 16など意味のわかるものをお願いします。
それに絡んで、int GrHandle[16];と決め打ちだったり、sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[0])なのを統一してください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

たいちう
記事: 418
登録日時: 13年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#23

投稿記事 by たいちう » 11年前

> それと先に書いてますが、適当にランダムシャッフルすると解けないパズルができます。

完成形から偶数回のswapだと必ず解けるような気がします。
少し自信がないので、シラフの時にまた考えてみますが、そんなに難しくないと思います。

とりあえず、解けるかどうかは後で心配することにして、
それ以外の実装を進めても良いのではないでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#24

投稿記事 by softya(ソフト屋) » 11年前

by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

ありがとうございます。

#25

投稿記事 by taka_taka » 11年前

softya(ソフト屋)様

>それに絡んで、int GrHandle[16];と決め打ちだったり、sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[0])なのを統一してください。

c言語の知識不足なのですが、ヘッダーの構造体で数字を文字の定数(16をNUM等)としたいときは、マクロの定数定義は使う感じになるのでしょうか。
それともstatic変数になるのでしょうか。

>Puzzle_tにint place[HANDLE_SIZE]を含まないとせっかくの構造体が中途半端になりますね。

含ませると考えずに、別々に書いてしまっていたので、含ませたいと思います。


>先に書いてますが、適当にランダムシャッフルすると解けないパズルができます。

難しそうですが、多少の時間をかけて、考慮してみます。

>あと、パズルピースの表示が15番目のピースを表示したら動くスペースがないですよ。

今迷っているのですが、1から15(インデックスは0から14)でピースを15とするか、
1から15とブラックボックスを含めて16(インデックスは0から15)とするかで迷っています。
コードは、ブラックボックスを含めない考えでやりました。

ただ、この先の実装を考えていない上での話しで申し訳ないです。
表示と、15個かブラックを含めた16個のピースの扱いどちらがよいのでしょうか。


たいちう様

偶数回のswapがポイントなのですね。
自分でもsoftya(ソフト屋)様の情報を元に考えてみますが、難しそうです。
最後に編集したユーザー taka_taka on 2013年1月18日(金) 17:54 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#26

投稿記事 by softya(ソフト屋) » 11年前

taka_taka さんが書きました:>あと、パズルピースの表示が15番目のピースを表示したら動くスペースがないですよ。

今迷っているのですが、1から15(インデックスは0から14)でピースを15とするか、
1から15とブラックボックスを含めて16(インデックスは0から15)とするかで迷っています。
コードは、ブラックボックスを含めない考えでやりました。

ただ、この先の実装を考えていない上での話しで申し訳ないです。
表示と、15個かブラックを含めた16個のピースの扱いどちらがよいのでしょうか。
こういうのは出来るだけ単純な方が良いので、ブラックボックスを含めて処理したほうが良いと思います。
そうすれば表示しない所だけ考えれば良いので、他の所は普通に16パーツ目を扱って良いことになります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

ありがとうございます。

#27

投稿記事 by taka_taka » 11年前

ブラックボックスを含めて処理をすることにしました。

シャッフル、定数等、課題はありますが、とりあえずマウス処理と移動処理に行きたいと思います。

マウス処理は、制御というか、使い方が難しい感じです。

mainにそのまま組み込むとすると、クリックしたときの情報をどうやって得ればいいのか分かりません。

mainに入れるという考え方が間違っていますでしょうか。

例えば、下記をループに入れる等になると考えています。

前略

コード:

 
MouseInput = GetMouseInput() ;
	while( ( MouseInput & MOUSE_INPUT_LEFT ) == 0 )
	{
		// メッセージ処理
		if( ProcessMessage() == -1 )
		{
			break ;	// エラーが起きたらループから抜ける
		}

		// マウスの入力を得る
		MouseInput = GetMouseInput() ;
	}
GetMousePoint(MouseX, MouseY );
後略

nil
記事: 428
登録日時: 12年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#28

投稿記事 by nil » 11年前

大分と前ですが、それはsoftyaさんの仰ってた書いてはいけない処理です。
http://dixq.net/g/h_11.html

メインループの中に複数個のProcessMessageが存在してはなりません。
私ならばマウスの情報をまとめる構造体を作り、そこに左クリックやマウス座標などの情報を入れるかと思います。
ちょうどtaka_takaのコードで言うところのKeyboard構造体のように。
Keyboard_Update()の中身がしっかりと理解できているのであれば、
それと同様のものをマウス入力用に作るだけなので、特に問題はないように思えますがいかがでしょう?

taka_taka
記事: 79
登録日時: 11年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#29

投稿記事 by taka_taka » 11年前

そこで悩んでおります。
Keyboardのようにすると、クリックしたときに、座標を得る処理が
うまく考えられていません。
クリックを得て、どのタイミングで座標を得るのか、考え中です。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#30

投稿記事 by softya(ソフト屋) » 11年前

座標はクリック時に保存すれば良いと思います。知りたいのはクリックした座標ですから。
難しく考える必要はないと思いますが。

[追記]
涼雅さんの書かれた内容は理解されましたか? その事についても返答をお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

理解できてない部分と出来ている部分がある感じです。

#31

投稿記事 by taka_taka » 11年前

入れ子のループはいけないというのは、理解できております。

構造体の件は、キーボードのように、クリックしたタイミングで、
クリック情報は得られると思うのですが、そのときの座標は、
次の行で得たとして、
この場合、一つのwhile中で、得た情報を計算のupdateに
与える感じでよろしいのでしょうか。

1/60ずつ、上記の処理をおこなう感じでしょうか。

コードはこれからなので、感じという表現で申し訳ありません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#32

投稿記事 by softya(ソフト屋) » 11年前

与えるかupdateの中でチェックするかはお任せしますが、私に認識が間違っていなければOKだと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

ファイル分割について

#33

投稿記事 by taka_taka » 11年前

キーボードのときには、ファイル分割が有効でしたが、
マウスの場合、キーで得てくるというより関数でポインタ得てくるため、
ファイル分割の意味がないように感じられるのですが、
工夫が足りないのでしょうか。

GetMousePoint(x,y);
これをファイル分割中の関数の中に組み込みと、
いわゆるgetterがgetter_x, getter_yと、二つになる気がします。
配列を返せるならいいのですが、いずれにしても、
GetMousePoint(x,y);
を直接書いてもコード量として変わらない気がしています。

あとは、必要な情報が、左クリックと座標のためと、少なく
ただ、得るだけというのも分割の意味が少ない気もします。

ファイル分割はしたほうがいいのでしょうか。

nil
記事: 428
登録日時: 12年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#34

投稿記事 by nil » 11年前

softyaさんのおっしゃるとおりそこまで深く考える必要がありません。
複数の用途にマウスの座標を使用するのであれば別個に保存したほうが効率はよさそうですが、
今回のように狭い用途での仕様であれば深く考える必要はありません。

マウスボタンの入力状態を取得し、
クリックされている時に取得しても良いですし、
ボタンの入力と同時に取得しても良いです。

複数用途に使用する例としては、
マウスの載っているマスを光らせる、ボード外に表示させたボタンの画像をクリックしているかの判定などが有りましょうか。

taka_taka
記事: 79
登録日時: 11年前

ありがとうございます。

#35

投稿記事 by taka_taka » 11年前

>涼雅様

アドバイスありがとうございます。

前回の解答では、ファイル分割をkeyboardのように行うまではいいのですが、
まだ、実装できていないので、実装をしてみようと思います。
今までで、一番、判断が迷っています。

分割した際の、x , y情報をどう取り出すのかの部分です。

実装してみました。
とりあえず、パズルの端に、マウスの位置を表示させる感じです。
これから、クリックしたときにマウス位置を移動処理の中に格納を考えます。

コード:

//Mouse.cpp
//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Mouse.h"

//グローバル変数
static Mouse_t Mouse;

//マウスの入力状態更新
int Mouse_Update(){
	GetMousePoint( &Mouse.x , &Mouse.y) ;
	return 0;
}

//マウスの入力状態を取得する
int Mouse_Get_X(){
        return Mouse.x; // KeyCodeの入力状態を返す
}

int Mouse_Get_Y(){
        return Mouse.y; // KeyCodeの入力状態を返す
}

コード:

//Mouse.h
#ifndef DEF_MOUSE_H //二重include防止

#define DEF_MOUSE_H

typedef struct{

	int x , y; 	/*座標*/

	int button[8]; /*ボタンの押した状態*/

} Mouse_t;

// キーの入力状態を更新する
int Mouse_Update();

// 引数のキーコードのキーの入力状態を返す
int Mouse_Get_X();

int Mouse_Get_Y();

#endif 

コード:

//main.cpp
//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Keyboard.h"
#include "Mouse.h"
#include "Puzzle.h"


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

	int flag;
	
	char StrBuf[ 128 ] , StrBuf2[ 32 ];
	int StringCr;

	ChangeWindowMode(true); 

	if (DxLib_Init() != 0)
	{
		flag = MessageBox(
                NULL ,
                TEXT("DxLib_Init() err") ,
                TEXT("Err") , 
                MB_OK);
		if (flag == IDOK) return -1;
	}

	SetMouseDispFlag( TRUE ) ;

	if (SetDrawScreen(DX_SCREEN_BACK) != 0)
	{
		flag = MessageBox(
				NULL ,
				TEXT("SetDrawScreen(DX_SCREEN_BACK) err") ,
				TEXT("Err") , 
				MB_OK);
					
		if (flag == IDOK){
			DxLib_End();
			return -1;
		}
	}

	// 白色の値を取得
	StringCr = GetColor( 255 , 255 , 255 ) ;

	Puzzle_Initialize();

	while( 1 ){
		if( ScreenFlip() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ScreenFlip err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}
		if( ProcessMessage() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ProcessMessage err(End)") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}
		if( ClearDrawScreen() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ClearDrawScreen err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}

/*		if( Keyboard_Update() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("Keyboard_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}	
*/
		if( Mouse_Update() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("Mouse_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}	

	{	lstrcpy( StrBuf , "座標 X" ) ; // 文字列"座標 X"をStrBufにコピー	
		itoa( Mouse_Get_X() , StrBuf2 , 10 ) ; // Mouse_Get_X()の値を文字列にしてStrBuf2に格納
		lstrcat( StrBuf , StrBuf2 ) ; // StrBufの内容にStrBuf2の内容を付け足す
		lstrcat( StrBuf , " Y " ) ; // StrBufの内容に文字列" Y "を付け足す
		itoa( Mouse_Get_Y() , StrBuf2 , 10 ) ; // Mouse_Get_Y()の値を文字列にしてStrBuf2に格納
		lstrcat( StrBuf , StrBuf2 ) ; // StrBufの内容にStrBuf2の内容を付け足す
	}	
		DrawString( 400 , 400 , StrBuf , StringCr );

		//Puzzle_Update(&m_Puzzle, &i, &j);
		Puzzle_Draw();
		//WaitKey();	
	}

	Puzzle_Finalize();
	
	if (DxLib_End() != 0)
	{
		DrawFormatString(0, 0, GetColor(0, 0, 255), "DxLib_End err");
		return 0;
	}

	return 0;

}

nil
記事: 428
登録日時: 12年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#36

投稿記事 by nil » 11年前

良い感じだと思います。
気になったのは111行目からの処理ですね。
itoa関数は非推奨な関数であったはずなので、使わないほうが無難かと思います。
こういう時にこそDrawFormatStringを使いましょう。

次は、どのマスがクリックされたのかを調べるような処理、を作ると良いかと思います。

taka_taka
記事: 79
登録日時: 11年前

よかったです。ありがとうございます。

#37

投稿記事 by taka_taka » 11年前

パズルの端に、マウスの位置を表示させる感じで、
クリック処理を加えたコードを貼り付けます。

表示関数をDrawFormatStringに書き換えて、クリック時に表示に変えました。

この部分に表示ではなく、移動処理を組み込めばいいと思うのですが、
どうなのでしょうか?

コード:

//main.cpp
//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Keyboard.h"
#include "Mouse.h"
#include "Puzzle.h"


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

	int flag;
	
	int StringCr;

	ChangeWindowMode(true); 

	if (DxLib_Init() != 0)
	{
		flag = MessageBox(
                NULL ,
                TEXT("DxLib_Init() err") ,
                TEXT("Err") , 
                MB_OK);
		if (flag == IDOK) return -1;
	}

	SetMouseDispFlag( TRUE ) ;

	if (SetDrawScreen(DX_SCREEN_BACK) != 0)
	{
		flag = MessageBox(
				NULL ,
				TEXT("SetDrawScreen(DX_SCREEN_BACK) err") ,
				TEXT("Err") , 
				MB_OK);
					
		if (flag == IDOK){
			DxLib_End();
			return -1;
		}
	}

	// 白色の値を取得
	StringCr = GetColor( 255 , 255 , 255 ) ;

	Puzzle_Initialize();

	while( 1 ){
		if( ScreenFlip() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ScreenFlip err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}
		if( ProcessMessage() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ProcessMessage err(End)") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}
		if( ClearDrawScreen() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ClearDrawScreen err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}

/*		if( Keyboard_Update() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("Keyboard_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}	
*/
		if( Mouse_Update() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("Mouse_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}	
	
		if( ( Mouse_Get_Input() & MOUSE_INPUT_LEFT ) != 0 )
		{
			DrawFormatString( 400, 400, StringCr, "座標 X %d Y %d", Mouse_Get_X(), Mouse_Get_Y()) ;
			//Puzzle_Update(&m_Puzzle, &i, &j);
		}

		Puzzle_Draw();
	}

	Puzzle_Finalize();
	
	if (DxLib_End() != 0)
	{
		DrawFormatString(0, 0, GetColor(0, 0, 255), "DxLib_End err");
		return 0;
	}

	return 0;

}

コード:

//Mouse.cpp
//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Mouse.h"

//グローバル変数
static Mouse_t Mouse;

//マウスの入力状態更新
int Mouse_Update(){
	Mouse.MouseInput = GetMouseInput();
	GetMousePoint( &Mouse.x , &Mouse.y) ;
	return 0;
}

int Mouse_Get_Input(){
	return Mouse.MouseInput;
}
//マウスの入力状態を取得する
int Mouse_Get_X(){
        return Mouse.x; // KeyCodeの入力状態を返す
}

int Mouse_Get_Y(){
        return Mouse.y; // KeyCodeの入力状態を返す
}

コード:

//Mouse.h
#ifndef DEF_MOUSE_H //二重include防止

#define DEF_MOUSE_H

typedef struct{

	int x , y; 	/*座標*/

	int MouseInput; /*ボタンの押した状態*/

} Mouse_t;

//マウスの入力状態を更新する
int Mouse_Update();

//マウス入力状態を返す
int Mouse_Get_Input();
int Mouse_Get_X();

int Mouse_Get_Y();

#endif 
最後に編集したユーザー taka_taka on 2013年1月19日(土) 21:16 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#38

投稿記事 by softya(ソフト屋) » 11年前

ここで気を作る点を1つ。無闇にファイルと関数に小分けするとメンテンナンスが面倒になります。
原則として、何度も使ったりややこしいモノを別ファイルに分けます。
今回はこれでよいと思いますが、マウスに関しては直接書くより面倒になっているとおもいます。

>この部分に表示ではなく、移動処理を組み込めばいいと思うのですが、

トリガはそれで良いと思いますが、実際の入れ替え処理は Puzzle.cpp内で行ってください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

メンテナンス部分は考えていなかったので、助かります。

#39

投稿記事 by taka_taka » 11年前

softya(ソフト屋) さんが書きました: ここで気を作る点を1つ。
無闇にファイルと関数に小分けするとメンテンナンスが面倒になります。
原則として、何度も使ったりややこしいモノを別ファイルに分けます。
今回はこれでよいと思いますが、マウスに関しては直接書くより面倒になっているとおもいます。
ありがとうございます。
ゲームプログラミングをほとんどしたことがないので、参考になります。

入れ替え処理ですが、Puzzle.cpp内書いてみますが、ここが一番、難しそうです。
場所を0から15としたときに、前後左右調べると思いますが、
場合わけをどうしようか迷っています。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#40

投稿記事 by softya(ソフト屋) » 11年前

> ゲームプログラミングをほとんどしたことがないので、参考になります。

この原則は一般アプリやツールでも同じですよ。

ちなみに上下左右は添字で、-4、+4、-1、+1です。添字範囲外なら調べないという関数も必要かと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#41

投稿記事 by taka_taka » 11年前

プログラミングは、多分、かなりの初心者クラスだと思います。

場所番号0から15と、座標を絡めて、考えていますが、
例えば3と4(完成時の4と5の数字など)は、隣り合っていないので、
そこをどう判定しようか考えています。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#42

投稿記事 by softya(ソフト屋) » 11年前

配列に順番に並べば正解なのでは? 座標は見なくて良いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

分かりずらくて、すいません。

#43

投稿記事 by taka_taka » 11年前

完成の判定の前の、入れ替え処理での判定です。
上下左右に空きがあるかどうかの判定です。

場所は先ほどの数値で特定できるのですが、
物理的に隣かどうかとなると、難しいです。
いくつかやり方はありそうですが、いいのか悪いのか、
書いてみないと分かりませんが。

15番目を空のボックスとして、毎回15番目のplace[15]を
取り出して、クリックされた箇所のplaceが、place[15]の
上下左右であるかないか、判定するとかありそうですが
まだ、よくわかっていません。

いずれにしても、place[任意](クリック箇所のplace)もしくはplace[15]の
上下左右の指定が難しいところです。
+4. -4(y座標方向)は範囲外で判定できそうですが、+1 -1(x
座標方向)は、その値が、端ではないか、判定が別途必要な気がします。

コーディング前なので、気がします等の表現で申し訳ありません。
最後に編集したユーザー taka_taka on 2013年1月19日(土) 22:26 [ 編集 2 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#44

投稿記事 by softya(ソフト屋) » 11年前

クリックされたポイントからplaceの添字を求められると思いますが、それでは不都合なのですか?
この時上下左右のplaceの配列に15が入っていれば空きなのでは無いでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#45

投稿記事 by softya(ソフト屋) » 11年前

追記されてますね。

そうですね。忘れてましたが端判定は必要ですね。
方法としては、今の添字と-1や+1した添字を4で割った時の結果が違えばBADだとする方法です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

助かりました。

#46

投稿記事 by taka_taka » 11年前

その方針で、実装したいと思います。
やはり、ポイントは、 通し番号i に対して、 i/4になりそうな気がします。
実装してみたいと思いますが、ありがとうございます。

taka_taka
記事: 79
登録日時: 11年前

趣旨とずれますが、アプリやツールの分類。

#47

投稿記事 by taka_taka » 11年前

アプリといったら、現状、どういったものが主流なのでしょうか。
flash等なのでしょうか。
アプリやゲームを作る方々の間では、どういう認識なのでしょうか。
(開発環境がcとdxライブラリ以外にたくさんあるのはぞんぞじております。)
現在のいわゆるゲームやアプリという部分が知りたいです。

よろしければ、ご回答をお待ちしております。
これからどういった環境で開発すべきかの方向性を考えたいです。

今、ゲーム業界(ソーシャルも含めて)への就職を考えています。
(ブランクがあるので、就職活動にはつらい部分も多いのですが。)
最後に編集したユーザー taka_taka on 2013年1月20日(日) 20:10 [ 編集 2 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#48

投稿記事 by softya(ソフト屋) » 11年前

WEBアプリでは、HTML+css+Javascriptライブラリ(jQuery)がブラウザ側でサーバーサイド言語としPHP、perl、Javaなどが使われます。
スマホアプリは、iPhoneはobjective-CでAndroidはJavaですね。売れていないWindowsPhoneは保留します。
この2つのタイプのスマホは、上記のWEBアプリで提供される場合もあります。あるいはUnity3Dなどゲームエンジンで開発される場合もあります。ゲーム用のjavascriptライブラリとしてenchat.jsなどもありますね。
つまり、ソーシャル関係だけでもざっと上げただけで、これだけ作りかたにバリエーションが有るわけです。私の知らないのはもっとあると思います。

家庭用ゲーム機はC++が主流で大抵はライブラリはメーカーのオリジナルです。
GPUのAPIはDirectX、OpenGL、独自系など様々です。まぁ、移植性が悪いのでライブラリでラップしているはずです。
その他にメーカー独自のゲームエンジンやアンリアルエンジンやクライエンジンなどがあり、この場合はスクリプト記述も併用されます。
あとC#も少しづつ使われています。xbox360のダウンロードゲームで採用された例もあります。

就職できるレベルとなると3Dゲームは必然かと思います。
この話を続けるなら別トピックにされたほうが良いと思います。

[補足]
ソーシャルの場合は2Dゲームが作れれば良いとは思いますが、実際に作品を出せる必要があると思います。


【こっちに書いときますが転職は更に厳しいです】

●コンシューマ(家庭用ゲーム機)系
「中途採用(東京オフィス)|株式会社レベルファイブ」
http://www.level5.co.jp/creator/chuto02.html#t06
まぁコンシューマ開発経験2年位以上の人と同等レベル以上の物が作れる必要があるわけです。
「株式会社カプコン:開発職|中途採用|募集要項」
http://www.capcom.co.jp/recruit/dvp/mid ... ne_14.html
「株式会社カプコン:開発職|中途採用|募集要項」
http://www.capcom.co.jp/recruit/dvp/mid ... ne_11.html
「コナミグループ中途採用情報 デジタルエンタテインメント事業・ゲーミング&システム事業 他」
http://www.konami.co.jp/job/jk/spe/koji ... =koji_side
「SQUARE ENIX - RECRUITING -」
http://www.jp.square-enix.com/recruit/career/index.html

●ソーシャル系
「グリー株式会社 | 採用情報 | キャリア採用 | 募集職種 | Webアプリ, ソーシャルゲーム」
https://progres11.jposting.net/pggree/u ... b_code=535
「Careers at GREE | 特別選考」
http://jobs.gree.net/jp/ja/apply/selection/

「スマートフォン向けアプリケーションエンジニア | 株式会社ディー・エヌ・エー」
https://career.dena.jp/job.phtml?job_code=163
「エンジニア特集|株式会社ディー・エヌ・エー キャリア採用サイト」
http://www.dena.jp/recruit/engineer/engineer.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

お返事ありがとうございます。

#49

投稿記事 by taka_taka » 11年前

コンシューマ開発経験2年位、想像がつきません・・・すごそうです。
多分、中小企業になるかもしれません。

すいません、この話題は、別の時にでもお願いします。
ちなみに、就職といっても、転職になります。

とりあえず、15パズルをがんばってみます。
最後に編集したユーザー taka_taka on 2013年1月20日(日) 21:13 [ 編集 1 回目 ]

taka_taka
記事: 79
登録日時: 11年前

15パズルの移動処理について

#50

投稿記事 by taka_taka » 11年前

マウスの入力であるx、yを利用したいのですが、
xが

0<=x<100
100<=x<200
200<=x<300
300<=x<=400

で4通り、yも同様に4通りで、
計16通りの分岐を作る方法でよろしいでしょうか。
マウス入力x、yの利用のためには、ほかにやり方はなさそうです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#51

投稿記事 by softya(ソフト屋) » 11年前

100で割る計算だけで出来ると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

ありがとうございます。

#52

投稿記事 by taka_taka » 11年前

100で割るというのは考えつかなかったです。
その後に、場合わけになるのでしょうか。

すいません、考えてみると、そこから場所が求まりますね。
たとえば、
x/100 = 2
y/100 = 1
2 + 1 * 4 = 6

という計算ですよね。
その上で、場合わけして、実装してみます。
最後に編集したユーザー taka_taka on 2013年1月21日(月) 18:36 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#53

投稿記事 by softya(ソフト屋) » 11年前

まずマウスのx,yからパーツのx,yを求めます
px = mx / 100
py = my /100
これがそれぞれ0から3の範囲である事を確認します。
index = py * 4 + px
で配列のindexが求まりますので場合分けは必要ないです。

プログラミングは、こういう簡易化出来るルールをできるだけ見つけて行くことが重要です。
こうして、if文の分岐を減らす事でバグを減らし開発効率をアップさせるのです。
場合分けは、計算できなかった時の最後の手段だと思ってください。

数学で言えば数列のルールを見つけるような物と思ってもらえばよいでしょうか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

nil
記事: 428
登録日時: 12年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#54

投稿記事 by nil » 11年前

マウスの座標がx,yそれぞれ0以下の時も場合分けをしたほうが良いかと思います。
-1~-99までの数字を割る100しても0になるためです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#55

投稿記事 by softya(ソフト屋) » 11年前

失礼しました。先にチェックしたほうが良いですね。
ということで 0 <= mx < 400 と 0 <= my < 400 を先にチェックして、100で割った後のチェックは不要です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

マイナスも気づきませんでせんでした。

#56

投稿記事 by taka_taka » 11年前

お二人ともありがとうございます。
涼雅 さんが書きました:-1~-99までの数字を割る100しても0になるためです。
softya(ソフト屋) さんが書きました:0 <= mx < 400 と 0 <= my < 400 を先にチェックして、100で割った後のチェックは不要
すいません、一番、重要な部分でアドバイスというか、
お答えを頂いて、ありがとうございます。
indexを基に、上下左右にブラックボックス(PLACE[15])がないか、チェックをする感じでしょうか。
とりあえず、実装したいと思います。
softya(ソフト屋) さんが書きました:if文の分岐を減らす事でバグを減らし開発効率をアップさせる
分岐を減らして、バグも減り、テスト数も減るということでしょうか。

taka_taka
記事: 79
登録日時: 11年前

とりあえず、移動処理がかけました。

#57

投稿記事 by taka_taka » 11年前

大したゲームではございませんが、変な質問ですが、
ソースを公開したら、そのソースは、作品扱いにできなくなるものでしょうか。
そもそも15パズル程度では、作品にはならないものかもしれませんし、
皆様のアドバイスのおかげなので、公開すべきかもしれませんし、
まだ完成していないので載せて、アドバイスを頂きたくもあります。
最後に編集したユーザー taka_taka on 2013年1月21日(月) 20:13 [ 編集 1 回目 ]

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: とりあえず、移動処理がかけました。

#58

投稿記事 by h2so5 » 11年前

taka_taka さんが書きました:大したゲームではございませんが、変な質問ですが、
ソースを公開したら、そのソースは、作品扱いにできなくなるものでしょうか。
そもそも15パズル程度では、作品にはならないものかもしれませんし、
皆様のアドバイスのおかげなので、公開すべきかもしれませんが。
「作品扱い」とはどういう意味でしょうか?
規約に書かれている通り、ソースコードをここに貼ったとしても著作権は投稿者に帰属します。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: とりあえず、移動処理がかけました。

#59

投稿記事 by softya(ソフト屋) » 11年前

taka_taka さんが書きました:大したゲームではございませんが、変な質問ですが、
ソースを公開したら、そのソースは、作品扱いにできなくなるものでしょうか。
そもそも15パズル程度では、作品にはならないものかもしれませんし、
皆様のアドバイスのおかげなので、公開すべきかもしれませんが。
少なくとも就職活動の応募作品を自サイトで公開してはいけないというのは無いですが、全て自分の力で作ったものでないと意味が無いというのは確かです。
このレベルの物は全て自分で作れますよとアピールするためのものですから。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

理解いたしました。

#60

投稿記事 by taka_taka » 11年前

アドバイスありがとうございます。
以下、Puzzle.cppの移動処理追加コードです。
同じ処理の繰り返しのため、よくないかもしれません。

コード:

//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Keyboard.h"
#include "Puzzle.h"

//インクルード_標準
#include <stdlib.h>
#include <time.h>

//マクロ
#define BLOCK_SIZE 100
#define PAZZLE_PIECE_NUM 16
#define NUM_ZERO 0
#define NUM_BLACKBOX 15

//グローバル変数
static Puzzle_t Puzzle;

//関数定義
void swap(int *a, int *b){
	
	int temp = *a;
	*a = *b;
	*b = temp;
}

// 初期化をする
void Puzzle_Initialize(){
	
	int i;
	int a, b;

	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
		Puzzle.Place[i] = i;
	}

	srand((unsigned)time(NULL));
	
	for (i = PAZZLE_PIECE_NUM - 1; i > 1; i--)
	{
		a = i;
		b = rand() % i;
		swap(&Puzzle.Place[a], &Puzzle.Place[b]);
	}

	LoadDivGraph("C:/Documents and Settings/All Users/Documents/My Pictures/Sample Pictures/16puzzle01.png", 16, 4, 4, BLOCK_SIZE, BLOCK_SIZE, Puzzle.GrHandle);
	
}
// 動きを計算する
void Puzzle_Update(int MouseX, int MouseY){
	
	int click_blook_place;
	int i;
	
	if (0 <= MouseX && MouseX < 4 * BLOCK_SIZE && 0 <= MouseY && MouseY < 4 * BLOCK_SIZE )
	{
		click_blook_place = MouseX / 100 + MouseY / 100 * 4;
	
	} else {
		return;
	}
	
	int up = 0;
	int down = 0;
	int left = 0;
	int right = 0;

	up = click_blook_place - 4;
	
	if (up >= 0 && up == Puzzle.Place[NUM_BLACKBOX])
	{
		for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[NUM_ZERO]); i++)
		{
			if (Puzzle.Place[i] == click_blook_place)
			{
				swap(&Puzzle.Place[i], &Puzzle.Place[NUM_BLACKBOX]);
				return;
			}
		}
	}

	down = click_blook_place + 4;

	if (down >= 0 && down == Puzzle.Place[NUM_BLACKBOX])
	{
		for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[NUM_ZERO]); i++)
		{
			if (Puzzle.Place[i] == click_blook_place)
			{
				swap(&Puzzle.Place[i], &Puzzle.Place[NUM_BLACKBOX]);
				return;
			}
		}
	}

	if (click_blook_place % 4 == 0)left = -1;
	else left = click_blook_place - 1;

	if (left >= 0 && left == Puzzle.Place[NUM_BLACKBOX])
	{
		for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[NUM_ZERO]); i++)
		{
			if (Puzzle.Place[i] == click_blook_place)
			{
				swap(&Puzzle.Place[i], &Puzzle.Place[NUM_BLACKBOX]);
				return;
			}
		}
	}

	if (click_blook_place % 4 == 3)right = -1;
	else right = click_blook_place + 1;

	if (right >= 0 && right == Puzzle.Place[NUM_BLACKBOX])
	{
		for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[NUM_ZERO]); i++)
		{
			if (Puzzle.Place[i] == click_blook_place)
			{
				swap(&Puzzle.Place[i], &Puzzle.Place[NUM_BLACKBOX]);
				return;
			}
		}
	}
}

// 結果を完成と比較する
void Puzzle_Differ(){
	
	
// 全体を描画する
void Puzzle_Draw(){
	int i;

	for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[NUM_ZERO]); i++)
	{
		DrawGraph( BLOCK_SIZE * (Puzzle.Place[i] % 4), BLOCK_SIZE * (Puzzle.Place[i]/4), Puzzle.GrHandle[i], FALSE);
	}
}

//終了処理をする
void Puzzle_Finalize(){
	
	int i;
	
	for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[0]); i++)
	{
		DeleteGraph(Puzzle.GrHandle[i]);
	}
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#61

投稿記事 by softya(ソフト屋) » 11年前

このプログラムってちゃんと動いていますか?
一度全部のコードを見せてもらったほうが良いかもしれません。
zip添付で全部のソースコードと出来れば画像だけ入れてください。

怪しい所。

コード:

        for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[NUM_ZERO]); i++)
        {
            if (Puzzle.Place[i] == click_blook_place)
            {
                swap(&Puzzle.Place[i], &Puzzle.Place[NUM_BLACKBOX]);
                return;
            }
        }
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

はい、わかりました。

#62

投稿記事 by taka_taka » 11年前

zip形式のファイルです。
まだ途中ですが、環境もよくわからないですが、
VC++2008では動いてました。
添付ファイル
15Puzzle_ver1.zip
(3.55 KiB) ダウンロード数: 111 回

taka_taka
記事: 79
登録日時: 11年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#63

投稿記事 by taka_taka » 11年前

ブラックボックス用の画像がないので
16をブラックボックスとして考えてください。
添付ファイル
16puzzle01.png
16puzzle01.png (6.54 KiB) 閲覧数: 22670 回

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#64

投稿記事 by softya(ソフト屋) » 11年前

失礼しました。動いてますね。勘違いを見なおしてみます。
ちなみに黒くするのは、こうすれば良いのでは?

コード:

	
// 全体を描画する
void Puzzle_Draw(){
	int i;

	for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[NUM_ZERO]); i++)
	{
		if( NUM_BLACKBOX != i ) {
			DrawGraph( BLOCK_SIZE * (Puzzle.Place[i] % 4), BLOCK_SIZE * (Puzzle.Place[i]/4), Puzzle.GrHandle[i], FALSE);
		}
	}
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#65

投稿記事 by softya(ソフト屋) » 11年前

では、まとめ方に行きますね。

1.ほとんど同じ処理は共通関数に出来ます。ここですね。

コード:

        for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[NUM_ZERO]); i++)
        {
            if (Puzzle.Place[i] == click_blook_place)
            {
                swap(&Puzzle.Place[i], &Puzzle.Place[NUM_BLACKBOX]);
                return;
            }
        }
2.ただの条件文に出来るのでは?
if ( click_blook_place % 4 == 0 )left = -1;
else left = click_blook_place - 1;

3.ぱっと見に分かりづらいんで、PAZZLE_PIECE_NUMで良いのでは?
sizeof( Puzzle.GrHandle ) / sizeof( Puzzle.GrHandle[NUM_ZERO] )

4.up = click_blook_place - 4;とかの4もdefineしましょう。

5.コメントがほぼ無いので、コメントを付ける癖が欲しいです。

6.基礎が完成したら演出(エフェクト・音・スコアなど)を付けましょう。 ※ ここがゲームプログラマーのセンスを問われるところです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

関数に配列を渡すときにサイズがわからない点は、自分も気になりました。

#66

投稿記事 by taka_taka » 11年前

とりあえず、staticなグローバル変数として、
配列を定義すると、関数の中でもsizeofで要素数が得られるようで、助かりました。

ブラックボックスのアドバイスをありがとうございます。
完成判定処理と、シャッフルの回数を100回、500回など偶数
(そもそも14回のswapなので)回のシャッフルを考えています。
15パズルの完成非完成の記事は、理解不足になりますが。

入れ違いで申し訳ございません。
ひとつずつ、考慮していきたいです。
実装します。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#67

投稿記事 by softya(ソフト屋) » 11年前

まぁ、シャッフル前の状態に戻れば完成ですよね?
シャッフル前はどうなっていますか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#68

投稿記事 by taka_taka » 11年前

softya(ソフト屋) さんが書きました: 2.ただの条件文に出来るのでは?
if ( click_blook_place % 4 == 0 )left = -1;
else left = click_blook_place - 1;

5.コメントがほぼ無いので、コメントを付ける癖が欲しいです。

6.基礎が完成したら演出(エフェクト・音・スコアなど)を付けましょう。 ※ ここがゲームプログラマーのセンスを問われるところです。
2は、思いついていないですが、考えて見ます。

5のコメントですが、ゲームプログラムではどういう感じで書けばいいのでしょうか。
普段はというか、以前は、設計書や仕様書やテンプレート(企業のシステムです)を基にやっていたので、
基準が特にありません

6は、面白そうですが、難易度が高そうです。

その他のアドバイスは、とても参考になりました。書き直します。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#69

投稿記事 by softya(ソフト屋) » 11年前

コメントは業務用と変わるわけではありませんが、自分でコメントを付けたことがないんですね?
どちらにしても、やらないと出来るようになりませんので挑戦してみてください。
・ソースを見てすぐ分かることは書かない。
・何行か毎に書く(必要なら一行ごとに書く)
・人に対する説明だと思って書く。

> 6は、面白そうですが、難易度が高そうです。

そうしないとゲームとは言えませんよね。
凝りだすとキリがないぐらい色々出来ますので、ほどほどの所で止めるようにしましょう。
ただ、この部分が快感度とかに影響するんで重要なんですね。
センスの良いゲームは、まずここの出来が良いのです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

ありがとうございます。

#70

投稿記事 by taka_taka » 11年前

コメントは、簡単なものしかつけたことがありません。

/
softya(ソフト屋) さんが書きました: ・ソースを見てすぐ分かることは書かない。
・何行か毎に書く(必要なら一行ごとに書く)
・人に対する説明だと思って書く。
たとえば、結果を完成と比較する処理を書いているのですが、
この場合は、こういう感じでしょうか。
処理も正しいのでしょうか。

コード:

/*************************************************************************
* ファイル名   : Puzzle.cpp
* プログラム名 : パズル
* 作成日       : 2013/01/22
* Version      : 1.00
* 概要         : パズルの初期化処理、移動処理、完成判定処理、描画処理、終了処理をする
* 変更履歴  ;
**************************************************************************/

//略・・・・・・・・・・・・・・・・・

/************************************************
宣言 : Puzzle_Differ()
概略 : パズルの完成判定処理
引数 : なし
戻り値: int型   1 :完成
      int型 -1 :未完成
解説 ; パズルが1から15まで完成系に
     なっているかを判定する
*}*********************************************/
int Puzzle_Differ(){

	int i;
	int ok = 1;

              //白色の取得
	int white = GetColor( 255 , 255 , 255 ) ;

       //完成判定処理
	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
              //完成の位置とは異なる場合
		if (Puzzle.Place[i] != i) 
		{
			ok = 0;
		}
	}

       //完成している場合、"完成です!"を表示
	if (ok == 1) {
		DrawString(400, 400, "完成です!", white);
		return 1;
	}
	return -1;
}

//略・・・・・・・・・・・・・・・・・


アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#71

投稿記事 by softya(ソフト屋) » 11年前

「白色の取得」は見てわかるので不要ですね。

「完成判定処理」と「完成の位置とは異なる場合」は一行書いてしまって良いと思います。
例えば → Placeが元の位置の配置になっているかを判定して、ダメな場合はOKを0にする。

あと関数が判定機能以上のことをしてしまっているのは良くないです。
つまり、表示をしてはいけません。関数のコメントに書かれている事ともズレますから2重にダメです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#72

投稿記事 by taka_taka » 11年前

書き直すと以下のような感じでしょうか。

あとは、シャッフルとエフェクト系の処理に入りたいと思います。

コード:


/*************************************************************************
* ファイル名   : Puzzle.cpp
* プログラム名 : パズル
* 作成日       : 2013/01/22
* Version      : 1.00
* 概要         : パズルの初期化処理、移動処理、完成判定処理、描画処理、終了処理をする
* 変更履歴  ;
**************************************************************************/
 
//略・・・・・・・・・・・・・・・・・
 
/************************************************
宣言 : Puzzle_Differ()
概略 : パズルの完成判定処理
引数 : なし
戻り値: int型   1 :完成
      int型 -1 :未完成
解説 ; パズルが1から15まで完成系に
     なっているかを判定する
*}*********************************************/
int Puzzle_Differ(){
 
    int i;
    int ok = 1;
 
    int white = GetColor( 255 , 255 , 255 ) ;
 
  //Puzzle.Place[]が元の位置の配置になっているかを判定し、配置が異なる場合はOKを0にする
    for (i = 0; i < PAZZLE_PIECE_NUM; i++)
    {
        if (Puzzle.Place[i] != i) 
        {
            ok = 0;
        }
    }
 
    if (ok == 1) {
        return 1;
    }
    return -1;
}
 
//略・・・・・・・・・・・・・・・・・


アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#73

投稿記事 by softya(ソフト屋) » 11年前

int white = GetColor( 255 , 255 , 255 ) ;
は使っていないので不要ですね。

あと書き忘れていましたが、戻り値は0と1が良いと思います。
これならif文でそのまま判定できますね。 1なら真で0なら偽です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

アドバイスありがとうございます。

#74

投稿記事 by taka_taka » 11年前

細かい表現は色々と欠点があるかもしれませんが、
全体的な感じはこのようなコメント の仕方になりますでしょうか。
プログラム名は、必要ない場合もあるかもしれませんが、
大体このような感じで大丈夫でしょうか。

企業提出用のコメントは、相手方がプログラムに素人の場合も
あり、ひとつの文章として、見られるものでなければとは、
感覚として持っていますが、ゲームプログラムやライブラリを用いると
どこまで書けばいいのか、慣れていません。

コード:

/*************************************************************************
* ファイル名   : Puzzle.cpp
* プログラム名 : パズル
* 作成日       : 2013/01/22
* Version      : 1.00
* 概要         : パズルの初期化処理、移動処理、完成判定処理、描画処理、終了処理をする
* 変更履歴  ;
**************************************************************************/

//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Keyboard.h"
#include "Puzzle.h"

//インクルード_標準
#include <stdlib.h>
#include <time.h>

//マクロ
#define BLOCK_SIZE 100
#define PAZZLE_PIECE_NUM 16
#define NUM_ZERO 0
#define NUM_BLACKBOX 15

//グローバル変数
static Puzzle_t Puzzle;

//関数定義
/************************************************
宣言	:	swap(int *a, int *b)
概略	:	与えられた二つの引数の値の交換
引数	:	int *a, int *b
戻り値	:	なし
解説	;	与えられた二つのポインタにより、
			呼び出しもとの二つの変数の値を
			入れ替える
*}*********************************************/
void swap(int *a, int *b){
	
	int temp = *a;
	*a = *b;
	*b = temp;
}

/*********************************************************
宣言	:	blackbox_swap(int click_blook_place)
概略	:	引数のblick_blook_placeの上下左右の
			位置にblackboxがないかどうか判定し、あれば
			入れ替える
引数	:	int *a, int *b
戻り値	:	なし
解説	;	Puzzle.Placeの位置が、引数の値cblick_blook_plac]と一致すれば、
              swapする。
*}********************************************************/
void blackbox_swap(int click_blook_place){

	int i;

	//クリックした位置のパズルと、ブラックボックスの
	//位置を交換する。
	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
		if (Puzzle.Place[i] == click_blook_place)
		{
			swap(&Puzzle.Place[i], &Puzzle.Place[NUM_BLACKBOX]);
			return;
		}
	}

/*********************************************************
宣言	:	Puzzle_Initialize()
概略	:	Puzzle.Place[]の初期化し、シャッフルを行う。
			たとえば、Puzzle.Place[i]は、画像分割のi番目
			の15パズル上での位置を示す。
			(位置は、基本的に通し番号0から15で扱う)
引数	:	iなし
戻り値	:	なし
解説	;	uzzle.Place[]の初期化、すなわち1から15の値を
			セットする。次に、ランダムswapを行う。さらに、
			LoadDivGraphにより画像の分割をする
*}********************************************************/
void Puzzle_Initialize(){
	
	int i;
	int a, b;

	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
		Puzzle.Place[i] = i;
	}

	srand((unsigned)time(NULL));
	
	for (i = PAZZLE_PIECE_NUM - 1; i > 1; i--)
	{
		a = i;
		b = rand() % i;
		swap(&Puzzle.Place[a], &Puzzle.Place[b]);
	}

	LoadDivGraph("C:/Documents and Settings/All Users/Documents/My Pictures/Sample Pictures/16puzzle01.png", 16, 4, 4, BLOCK_SIZE, BLOCK_SIZE, Puzzle.GrHandle);
	
}

/************************************************
宣言	:	Puzzle_Update(int MouseX, int MouseY)
概略	:	パズルの移動処理
引数	:	int MouseX, int MouseY
戻り値	:	なし
解説	;	引数のマウス位置から、クリック位置を
			特定する。クリック位置の上下左右にブ
			ラックボックスが存在する場合は、交換
			を行う
*}*********************************************/
void Puzzle_Update(int MouseX, int MouseY){
	
	int click_blook_place;
	
	//マウスのクリック座標を判定し、該当パズルの位置を求める。
	if (0 <= MouseX && MouseX < 4 * BLOCK_SIZE && 0 <= MouseY && MouseY < 4 * BLOCK_SIZE )
	{
		click_blook_place = MouseX / 100 + MouseY / 100 * 4;
	
	} else {
		return;
	}
	
	int up = 0;
	int down = 0;
	int left = 0;
	int right = 0;

	up = click_blook_place - 4;
	
	//クリックされたパズルの上にブラックボックスがある場合、
	//交換を行う。
	if (up >= 0 && up == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
	}

	down = click_blook_place + 4;

	//クリックされたパズルの下にブラックボックスがある場合、
	//交換を行う。
	if (down >= 0 && down == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
	}

	if (click_blook_place % 4 == 0)left = -1;
	else left = click_blook_place - 1;

	//クリックされたパズルの左にブラックボックスがある場合、
	//交換を行う。
	if (left >= 0 && left == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
	}

	if (click_blook_place % 4 == 3)right = -1;
	else right = click_blook_place + 1;

	//クリックされたパズルの右にブラックボックスがある場合、
	//交換を行う。
	if (right >= 0 && right == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
	}
}

/************************************************
宣言 : Puzzle_Differ()
概略 : パズルの完成判定処理
引数 : なし
戻り値: int型   1 :完成
      int型 -1 :未完成
解説 ; パズルが1から15まで完成系に
     なっているかを判定する
*}*********************************************/
int Puzzle_Differ(){
 
    int i;
    int ok = 1;
 
    int white = GetColor( 255 , 255 , 255 ) ;
 
  //Puzzle.Place[]が元の位置の配置になっているかを判定し、配置が異なる場合はOKを0にする
    for (i = 0; i < PAZZLE_PIECE_NUM; i++)
    {
        if (Puzzle.Place[i] != i) 
        {
            ok = 0;
        }
    }
 
    if (ok == 1) {
        return 1;
    }
    return 0;
}

/************************************************
宣言 : Puzzle_Draw()
概略 : パズルの描画処理
引数 : なし
戻り値:  なし
解説 ; パズル0から15までを描画する
*}*********************************************/	
// 全体を描画する
void Puzzle_Draw(){
	int i;

	//ブラックボックスでなければ、Puzzle.Place[]の位置で、パズル1から15を描画する
	for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[NUM_ZERO]); i++)
	{
		if (i != NUM_BLACKBOX)
		{
			DrawGraph( BLOCK_SIZE * (Puzzle.Place[i] % 4), BLOCK_SIZE * (Puzzle.Place[i]/4), Puzzle.GrHandle[i], FALSE);
		}
	}
}

/************************************************
宣言 : Puzzle_Draw()
概略 : パズルの終了処理
引数 : なし
戻り値:  なし
解説  ;  関数DeleteGraphにより、パズル1から15と、
     ブラックボックスのの終了処理を行う
*}*********************************************/
void Puzzle_Finalize(){
	
	int i;
	
	for (i = 0; i < sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[0]); i++)
	{
		DeleteGraph(Puzzle.GrHandle[i]);
	}
}
最後に編集したユーザー taka_taka on 2013年1月23日(水) 20:37 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#75

投稿記事 by softya(ソフト屋) » 11年前

私の趣味からすると若干説明がクドいかなって気もしますが概ねOKです。
ところどころコメントの残骸やら処理とコメントのズレも見受けられえるので、見なおしておいてください。
詳しく説明を書くほどメンテンナス性が悪くなると言う典型だと思いますので、もっと簡素にしないと面倒みきれないかもしれません。

あと
sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[NUM_ZERO])
とか
sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[0])
とか不統一な所も未うけら得ます。
全部PAZZLE_PIECE_NUMでも問題はないと思いますが如何でしょうか?

ところで、これコンパイル通ります?
blackbox_swapで閉じ括弧の数が合わないようですが。

あっPuzzle_Initializeって概略のほうが説明より長いですね。
概略になっていないと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

アドバイスが助かります。

#76

投稿記事 by taka_taka » 11年前

softya(ソフト屋) さんが書きました: 詳しく説明を書くほどメンテンナス性が悪くなると言う典型

あと
sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[NUM_ZERO])
とか
sizeof(Puzzle.GrHandle)/sizeof(Puzzle.GrHandle[0])
とか不統一な所も未うけら得ます。
全部PAZZLE_PIECE_NUMでも問題はないと思いますが如何でしょうか?

ところで、これコンパイル通ります?
blackbox_swapで閉じ括弧の数が合わないようですが。

あっPuzzle_Initializeって概略のほうが説明より長いですね。
概略になっていないと思います。
・なるほど、詳しく書くとメンテナンス性が悪くなるんですね。
 手が出せないという感じで、やりずらいと思ったことはあります。

・PAZZLE_PIECE_NUMに関しては、こちらのミスです。訂正しました。

・コンパイルが通るように書き直しました。

コード:

/*************************************************************************
* ファイル名   : Puzzle.cpp
* プログラム名 : パズル
* 作成日       : 2013/01/22
* Version      : 1.00
* 概要         : パズルの初期化処理、移動処理、完成判定処理、描画処理、終了処理をする
* 変更履歴  ;
**************************************************************************/

//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Keyboard.h"
#include "Puzzle.h"

//インクルード_標準
#include <stdlib.h>
#include <time.h>

//マクロ
#define BLOCK_SIZE 100
#define PAZZLE_PIECE_NUM 16
#define NUM_BLACKBOX 15

//グローバル変数
static Puzzle_t Puzzle;

//関数定義
/************************************************
宣言	:	swap(int *a, int *b)
概略	:	与えられた二つの引数の値の交換
引数	:	int *a, int *b
戻り値	:	なし
解説	;	与えられた二つのポインタにより、
			呼び出しもとの二つの変数の値を
			入れ替える
*}*********************************************/
void swap(int *a, int *b){
	
	int temp = *a;
	*a = *b;
	*b = temp;
}

/*********************************************************
宣言	:	blackbox_swap(int click_blook_place)
概略	:	blackboxがないか判定、ある場合は
			blackboxと引数のパズルを入れ替える
引数	:	int *a, int *b
戻り値	:	なし
解説	;	blackboxがないか判定、ある場合は
			blackboxと引数のパズルを入れ替える
*}********************************************************/
void blackbox_swap(int click_blook_place){

	int i;

	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
		
		if (Puzzle.Place[i] == click_blook_place)
		{
			//ブラックボックスとの位置を交換する。
			swap(&Puzzle.Place[i], &Puzzle.Place[NUM_BLACKBOX]);
			return;
		}
	}
}
/*********************************************************
宣言	:	Puzzle_Initialize()
概略	:	Puzzle.Place[]の初期化し、シャッフルを行う。
引数	:	なし
戻り値	:	なし
*}********************************************************/
void Puzzle_Initialize(){
	
	int i;
	int a, b;

	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
		Puzzle.Place[i] = i;
	}

	srand((unsigned)time(NULL));
	//シャッフル
	for (i = PAZZLE_PIECE_NUM - 1; i > 1; i--)
	{
		a = i;
		b = rand() % i;
		swap(&Puzzle.Place[a], &Puzzle.Place[b]);
	}

	LoadDivGraph("C:/Documents and Settings/All Users/Documents/My Pictures/Sample Pictures/16puzzle01.png", 16, 4, 4, BLOCK_SIZE, BLOCK_SIZE, Puzzle.GrHandle);
	
}

/************************************************
宣言	:	Puzzle_Update(int MouseX, int MouseY)
概略	:	パズルの移動処理
引数	:	int MouseX, int MouseY
戻り値	:	なし
*}*********************************************/
void Puzzle_Update(int MouseX, int MouseY){
	
	int click_blook_place;
	
	//パズルの位置を求める。
	if (0 <= MouseX && MouseX < 4 * BLOCK_SIZE && 0 <= MouseY && MouseY < 4 * BLOCK_SIZE )
	{
		click_blook_place = MouseX / 100 + MouseY / 100 * 4;
	
	} else {
		return;
	}
	
	int up = 0;
	int down = 0;
	int left = 0;
	int right = 0;

	up = click_blook_place - 4;
	
	//ブラックボックスに該当する場合、交換を行う。
	if (up >= 0 && up == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
	}

	down = click_blook_place + 4;

	//ブラックボックスに該当する場合、交換を行う。
	if (down >= 0 && down == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
	}

	if (click_blook_place % 4 == 0)left = -1;
	else left = click_blook_place - 1;

	//ブラックボックスが該当する場合、交換を行う。
	if (left >= 0 && left == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
	}

	if (click_blook_place % 4 == 3)right = -1;
	else right = click_blook_place + 1;

	//ブラックボックスが該当する場合、交換を行う。
	if (right >= 0 && right == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
	}
}

/************************************************
宣言 : Puzzle_Differ()
概略 : パズルの完成判定処理
引数 : なし
戻り値: int型   1 :完成
     int型 -1 :未完成
*}*********************************************/
int Puzzle_Differ(){
 
    int i;
    int ok = 1;
 
    int white = GetColor( 255 , 255 , 255 );
	
	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
    {
        ////Puzzle.Place[]が元の位置の配置になっているかを判定し、配置が異なる場合はOKを0にする
        if (Puzzle.Place[i] != i) 
        {
            ok = 0;
        }
    }
 
    if (ok == 1) {
        return 1;
    }
    return 0;
}

/************************************************
宣言 : Puzzle_Draw()
概略 : パズルの描画処理
引数 : なし
戻り値:  なし
*}*********************************************/	
void Puzzle_Draw(){
	int i;

	//ブラックボックスでなければ、Puzzle.Place[]の位置で、パズル1から15を描画する
	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
		if (i != NUM_BLACKBOX)
		{
			DrawGraph( BLOCK_SIZE * (Puzzle.Place[i] % 4), BLOCK_SIZE * (Puzzle.Place[i]/4), Puzzle.GrHandle[i], FALSE);
		}
	}
}

/************************************************
宣言 : Puzzle_Draw()
概略 : パズルの終了処理
引数 : なし
戻り値:  なし
*}*********************************************/
void Puzzle_Finalize(){
	
	int i;
	
	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
		DeleteGraph(Puzzle.GrHandle[i]);
	}
}
 

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#77

投稿記事 by softya(ソフト屋) » 11年前

じゃあ、次に行ってみましょう。
コメントもほどほどにです。無さ過ぎるのも困りますけどね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

いつも助かります。

#78

投稿記事 by taka_taka » 11年前

シャッフルと、エフェクト系の実装します。

ありがとうございます。

taka_taka
記事: 79
登録日時: 11年前

シャッフル回数の実装について

#79

投稿記事 by taka_taka » 11年前

ユーザーから100回、500回、1000回と入力を求めるか、
あらかじめ500回等決められた回数にするか迷っています。

前者の場合、三つのボックスを表示して選択させる感じになりそうです。

どちらがよろしいのでしょうか。また、別のいい方法があるのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#80

投稿記事 by softya(ソフト屋) » 11年前

遊ぶ人にとって、それが重要なことなのか考えてみたらどうでしょうか?
ユーザーから見たら、100回、500回、1000回は選択する必要がある事とは思えません。
分かりやすい難易度調節なら別ですが、それは意味が無いのではないでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

シャッフル回数の選択は意味が余りない気がします。

#81

投稿記事 by taka_taka » 11年前

そうですね、意味がないので、今回はシャッフルの回数は、実装なしにします。

完成判定処理のmainでの扱いがよくわかりませんでした。
とりあえず実装したのですが、いかがでしょうか。


あと、追記で申し訳ございませんが、SoHandleを使って、
クリック時に効果音を出すコードを書き加えましたが、音が出ませんでした。

コード:

//main.cpp
//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Keyboard.h"
#include "Mouse.h"
#include "Puzzle.h"

/* ************************************** *
 * 関数名 :WINAPI WinMain                *
 * 概要   :ここからプログラムが動き出す  *
 * 戻り値 :0                             *
 * ************************************** */
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

	int flag;
	
	int StringCr;

	int SoHandle;
	SoHandle = LoadSoundMem("C:/Documents and Settings/All Users/Documents/My Music/Sample Music/se_maoudamashii_onepoint25.ogg");
	
	ChangeWindowMode(true); 

	if (DxLib_Init() != 0)
	{
		flag = MessageBox(
                NULL ,
                TEXT("DxLib_Init() err") ,
                TEXT("Err") , 
                MB_OK);
		if (flag == IDOK) return -1;
	}

	SetMouseDispFlag( TRUE ) ;

	if (SetDrawScreen(DX_SCREEN_BACK) != 0)
	{
		flag = MessageBox(
				NULL ,
				TEXT("SetDrawScreen(DX_SCREEN_BACK) err") ,
				TEXT("Err") , 
				MB_OK);
					
		if (flag == IDOK){
			DxLib_End();
			return -1;
		}
	}

	// 白色の値を取得
	StringCr = GetColor( 255 , 255 , 255 ) ;

	Puzzle_Initialize();

	while( 1 ){
		if( ScreenFlip() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ScreenFlip err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}
		if( ProcessMessage() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ProcessMessage err(End)") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}
		if( ClearDrawScreen() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("ClearDrawScreen err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}

/*		if( Keyboard_Update() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("Keyboard_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}	
*/
		if( Mouse_Update() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("Mouse_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			if (flag == IDOK){
				break;
			}
		}	
	
		if( ( Mouse_Get_Input() & MOUSE_INPUT_LEFT ) != 0 )
		{
			 PlaySoundMem( SoHandle, DX_PLAYTYPE_BACK );
			 DrawFormatString( 400, 400, StringCr, "座標 X %d  Y %d", Mouse_Get_X(), Mouse_Get_Y()) ;
			Puzzle_Update(Mouse_Get_X(), Mouse_Get_Y());
		}

		Puzzle_Draw();
		if (Puzzle_Differ() == 1)
		{
			DrawFormatString( 400, 400, StringCr, "完成です!") ;
			break;
		}
	}

	Puzzle_Finalize();
	
	if (DxLib_End() != 0)
	{
		DrawFormatString(0, 0, GetColor(0, 0, 255), "DxLib_End err");
		return 0;
	}

	return 0;

}
最後に編集したユーザー taka_taka on 2013年1月25日(金) 20:04 [ 編集 2 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#82

投稿記事 by softya(ソフト屋) » 11年前

コメントが無い以外は問題はないと思います。
それとif (Puzzle_Differ() == 1)ならif ( Puzzle_Differ() )でOKです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

効果音について

#83

投稿記事 by taka_taka » 11年前

先のコードに追記したのですが、
PlaySoundMem( SoHandle, DX_PLAYTYPE_BACK )
の使い方が間違っているのでしょうか。

効果音が鳴りません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#84

投稿記事 by softya(ソフト屋) » 11年前

まず、PlaySoundFileで鳴ることは確認しましたか?
常にデバッグの方法を考えながらプログラミングをしましょう。
これはアプリでもゲームでも同じです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: シャッフル回数の選択は意味が余りない気がします。

#85

投稿記事 by ISLe » 11年前

taka_taka さんが書きました:そうですね、意味がないので、今回はシャッフルの回数は、実装なしにします。
意味がないのは「プレイヤーにシャッフルの回数を選択させること」であって実装することに意味がないわけではないのでは?
シャッフルの回数を変えることによって何が変わるのかを具体的に示す必要があると思います。

プレイヤー視点という点では、ふつうにウィンドウを閉じると「エラー」と書かれたダイアログが表示されるのも問題があるのではないでしょうか。
taka_taka さんが書きました:クリック時に効果音を出すコードを書き加えましたが、音が出ませんでした。
DxLib_Initを呼び出すより前にLoadSoundMemを呼び出しているせいではないかと思います。
戻り値のチェックを適切に行いましょう。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#86

投稿記事 by h2so5 » 11年前

DxLib_End()を実行した時点で描画処理は終了するのでDrawFormatString()を実行しても意味がありません。
ウィンドウのハンドリングも終了するため、画面上にエラーを通知する方法が無いということになります。

なのでDxLib_End()のエラーチェックは不要だと思います。

nil
記事: 428
登録日時: 12年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#87

投稿記事 by nil » 11年前

いくつか気になったことがあったので書き込みをします。

第一は文字エンコードの統一性の無さです。
MessageBoxではTEXTマクロが使われているのにその他の関数では使われていません。
これではUnicodeでコンパイルをした時にはエラーが発生しますし、
マルチバイトでコンパイルをすることを前提としたものとしてTEXTマクロを使わずにすべての文字列を表すか、
Unicodeでコンパイルすることを前提として文字列リテラルの先頭にLを付与したもので表すか、
あるいはTEXTマクロを全文字列リテラルに使用すべきかと思います。

第二にエラー発生時にMessageBox関数の返り値を判定してメインループを終了していますが、
エラーが起きた場合は(復旧可能なエラーを除き)すぐさま終了すべきであり、
つまり、MessageBox()の返り値がIDOKでなくともすぐにメインループを抜けるべきです。
なのでif( flag == IDOK )という判定は必要ありません。

第三にDrawFormatStringの使い方です。
DrawFormatStringの可変長引数を使用しない場合はこれを使うべきではありません。
素直にDrawStringを使ったほうが良いです。
何故ならば、可変長引数とは根本的に安全なものではなく、ただ便利だからという理由で濫用すべきではないものだからです。

taka_taka
記事: 79
登録日時: 11年前

皆様、貴重なアドバイスをありがとうございます。

#88

投稿記事 by taka_taka » 11年前

・効果音の件は、初期化より前に関数を使っているので、
解決しそうです。

・そのほかのアドバイスですが、一つずつ考慮していきたいと思いますので、
今後、実装に繁栄してみます。
最後に編集したユーザー taka_taka on 2013年1月28日(月) 01:32 [ 編集 2 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#89

投稿記事 by softya(ソフト屋) » 11年前

他の方の回答を見れば一目瞭然なのと、いろんなアドバイスが出ているで対応をお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
へにっくす
記事: 634
登録日時: 11年前
住所: 東京都

Re: 効果音について

#90

投稿記事 by へにっくす » 11年前

taka_taka さんが書きました:SoHandleを使って、
クリック時に効果音を出すコードを書き加えましたが、音が出ませんでした。
どこか誤りがございますでしょうか。
すでに指摘されています。
ISLeさんの投稿が的を射ていると思いますが?
それと他の人のアドバイスもちゃんと見てますか?
written by へにっくす

taka_taka
記事: 79
登録日時: 11年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#91

投稿記事 by taka_taka » 11年前

softya(ソフト屋) さんが書きました: まず、PlaySoundFileで鳴ることは確認しましたか?
常にデバッグの方法を考えながらプログラミングをしましょう。
これはアプリでもゲームでも同じです。
一応、dxライブラリのサンプルで、素材自体の音はなることは確認いたしました。
おそらく、初期化行と、ロード行の前後を入れ替えるとできると思います。
明日にでも実装します。

taka_taka
記事: 79
登録日時: 11年前

アドバイスをありがとうございます。

#92

投稿記事 by taka_taka » 11年前

>ISLe様
初心者にアドバイスを頂きまして、感謝します。
他の方々のアドバイスもそうですが、自分ではまったく気づかない部分もあり、
経験不足・力不足を痛感しているしだいでございます。
また、気になる部分がございましたら、助言をいただけますと、非常に助かります。
ISLe さんが書きました: 意味がないのは「プレイヤーにシャッフルの回数を選択させること」であって実装することに意味がないわけではないのでは?
シャッフルの回数を変えることによって何が変わるのかを具体的に示す必要があると思います。

プレイヤー視点という点では、ふつうにウィンドウを閉じると「エラー」と書かれたダイアログが表示されるのも問題があるのではないでしょうか。
シャッフルの件は、
>シャッフルの回数を変えることによって何が変わるのかを具体的に示す必要がある
の部分の理解が自分ではできていませんので、もう少し時間がかかりそうです。

>ふつうにウィンドウを閉じると「エラー」と書かれたダイアログが表示される
これは、意図的に、練習目的で残している部分もあるので、最終版?では直したいと考えております。
ISLe さんが書きました: DxLib_Initを呼び出すより前にLoadSoundMemを呼び出しているせいではないかと思います。
戻り値のチェックを適切に行いましょう。
ありがとうございます。実装は、明日にでもしたいと思います。
おそらく、そうだと自分も思いました。

taka_taka
記事: 79
登録日時: 11年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#93

投稿記事 by taka_taka » 11年前

>h2so5様

ありがとうございます。

h2so5 さんが書きました: DxLib_End()を実行した時点で描画処理は終了するのでDrawFormatString()を実行しても意味がありません。
ウィンドウのハンドリングも終了するため、画面上にエラーを通知する方法が無いということになります。

なのでDxLib_End()のエラーチェックは不要だと思います。
気がつきませんでしたが、ライブラリの終了ごに、
関数を呼び出しても意味がないのは、言われると当たり前で、気づかないで
申し訳ありません。
ご指摘していただきまして、感謝しています。

明日、明後日あたりに実装します。

taka_taka
記事: 79
登録日時: 11年前

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#94

投稿記事 by taka_taka » 11年前

>涼雅様

貴重なアドバイスありがとうございます。
自分には高度な部分もありますが、がんばってみます。
技術的な部分で、気になりました部分がございましたら、
遠慮なく言っていただけると助かります。
他の方のアドバイスと並行すると、混乱しますが、助かります。

涼雅 さんが書きました:
第一は文字エンコードの統一性の無さです。
MessageBoxではTEXTマクロが使われているのにその他の関数では使われていません。
これではUnicodeでコンパイルをした時にはエラーが発生しますし、
マルチバイトでコンパイルをすることを前提としたものとしてTEXTマクロを使わずにすべての文字列を表すか、
Unicodeでコンパイルすることを前提として文字列リテラルの先頭にLを付与したもので表すか、
あるいはTEXTマクロを全文字列リテラルに使用すべきかと思います。

第二にエラー発生時にMessageBox関数の返り値を判定してメインループを終了していますが、
エラーが起きた場合は(復旧可能なエラーを除き)すぐさま終了すべきであり、
つまり、MessageBox()の返り値がIDOKでなくともすぐにメインループを抜けるべきです。
なのでif( flag == IDOK )という判定は必要ありません。

第三にDrawFormatStringの使い方です。
DrawFormatStringの可変長引数を使用しない場合はこれを使うべきではありません。
素直にDrawStringを使ったほうが良いです。
何故ならば、可変長引数とは根本的に安全なものではなく、ただ便利だからという理由で濫用すべきではないものだからです。

第一について。TEXTマクロ側からないので、まず調べることからはじめたいと思います。

第二について、MessageBox関数は教えていただき、調べましたが、なるほど、
返り値に限らず、ループを抜けるべきなんですね。実装します。

第三について、一箇所?かもしれませんが、"完成です"の部分は、訂正し忘れなので、なおします。

taka_taka
記事: 79
登録日時: 11年前

個人的なことで申し訳ありませんが、

#95

投稿記事 by taka_taka » 11年前

>softya(ソフト屋)ならびに皆様方

インフルエンザにかかり、どうしても思考が普段どおりでなかったので、
コメントや対応が遅れました。

色々と、申し訳ありませんでした。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#96

投稿記事 by softya(ソフト屋) » 11年前

いえいえ,お体を一番に考えて下さい。一刻一秒を争うものではありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

連打したような効果音はどうしたらよろしいのでしょうか?

#97

投稿記事 by taka_taka » 11年前

//Unicode対応コーディング
http://www.ruche-home.net/program/tips/unicode#t-macro

上記を見て、とりあえずTEXT()をつけました。
あと、シャッフルに関しては、回数を増やすと、どうなるかまだわかっていません。

効果音はなるようになりましたが、
1クリックでも連打したような効果音になります。これは、どうしたら、1クリックで
一度だけなるようにできるのでしょうか。
たしかループは1秒に60回るのですが、countをいれる方法でしょうか?
もしくは、クリックではなく、移動処理時に効果音の処理を組み込むべきでしょうか?

コード:

//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Keyboard.h"
#include "Mouse.h"
#include "Puzzle.h"

/* ************************************** *
 * 関数名 :WINAPI WinMain                *
 * 概要   :ここからプログラムが動き出す  *
 * 戻り値 :0                             *
 * ************************************** */
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

	//MessageBoxの戻り値用変数
	int flag;

	int StringCr;

	//LoadSoundMemの識別番号の格納変数
	int SoHandle;

	//ウィンドウモードに変更	
	ChangeWindowMode(true); 

	//DXライブラリ初期化
	if (DxLib_Init() != 0)
	{
		//エラーメッセージを表示
		flag = MessageBox(
                NULL ,
                TEXT("DxLib_Init() err") ,
                TEXT("Err") , 
                MB_OK);
		return -1;
	}

	//マウスカーソルの表示設定フラグのセット マウスカーソルの表示
	if (SetMouseDispFlag( TRUE ) != 0)
	{
		//エラーメッセージを表示
		flag = MessageBox(
				NULL ,
				TEXT("SetMouseDispFlag( TRUE )  err") ,
				TEXT("Err") , 
				MB_OK);
					
		//DXライブラリ使用の終了処理
		DxLib_End();
		return -1;
	}
	
	// 裏画面を使用
	if (SetDrawScreen(DX_SCREEN_BACK) != 0)
	{
		//エラーメッセージを表示
		flag = MessageBox(
				NULL ,
				TEXT("SetDrawScreen(DX_SCREEN_BACK) err") ,
				TEXT("Err") , 
				MB_OK);
					
		//DXライブラリ使用の終了処理
		DxLib_End();
		return -1;
	}

	// 白色の値を取得
	StringCr = GetColor( 255 , 255 , 255 ) ;

	//se_maoudamashii_onepoint25.wavをロードし、識別番号をSoHandleに格納
	SoHandle = LoadSoundMem("C:/Documents and Settings/All Users/Documents/My Music/Sample Music/se_maoudamashii_onepoint25.wav");

	//パズルの初期化
	Puzzle_Initialize();

	while( 1 ){

		// 裏画面の内容を表画面に表示
		if( ScreenFlip() != 0 ){
			//エラーメッセージを表示
			flag = MessageBox(
					NULL ,
					TEXT("ScreenFlip err") ,
					TEXT("Err") , 
					MB_OK);

				break;
		}
		
		//メッセージ処理
		if( ProcessMessage() != 0 ){
			//エラーメッセージを表示
			flag = MessageBox(
					NULL ,
					TEXT("ProcessMessage err(End)") ,
					TEXT("Err") , 
					MB_OK);
	
				break;
		}

		// 画面を初期化
		if( ClearDrawScreen() != 0 ){
			//エラーメッセージを表示
			flag = MessageBox(
					NULL ,
					TEXT("ClearDrawScreen err") ,
					TEXT("Err") , 
					MB_OK);
	
			break;
		}

/*		if( Keyboard_Update() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("Keyboard_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			break;
		}	
*/
		//マウスの入力状態更新
		if( Mouse_Update() != 0 ){
			//エラーメッセージを表示
			flag = MessageBox(
					NULL ,
					TEXT("Mouse_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			break;
		}
		
		//マウス左ボタンが押されているか調べる	
		if( ( Mouse_Get_Input() & MOUSE_INPUT_LEFT ) != 0 )
		{
			//効果音を出す
			PlaySoundMem( SoHandle, DX_PLAYTYPE_BACK );

			//DrawFormatString( 400, 400, StringCr, "座標 X %d  Y %d", Mouse_Get_X(), Mouse_Get_Y()) ;

			//パズルの移動処理
			Puzzle_Update(Mouse_Get_X(), Mouse_Get_Y());
		}

		//パズルの描画処理
		Puzzle_Draw();

		//パズルの完成を判定する処理
		if (Puzzle_Differ() == 1)
		{
			//完成の表示
			DrawString( 400, 400, TEXT("完成です!"), StringCr) ;
			break;
		}
	}

	//パズルの終了処理
	Puzzle_Finalize();
	
	//DXライブラリ使用の終了処理
	DxLib_End();

	//ソフトの終了
	return 0;

}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#98

投稿記事 by softya(ソフト屋) » 11年前

UNICODEに対応する書き方をする場合は文字列はTEXT()で統一して下さい。
LoadSoundMem()もTEXT()が必要ですし、charが必要な場所ではcharではなくTCHARで全て書きます。
面倒やらミスが多そうならcharで統一します。その場合は、マルチバイト文字を言語セットとして選択します。
taka_taka さんが書きました:効果音はなるようになりましたが、
1クリックでも連打したような効果音になります。これは、どうしたら、1クリックで
一度だけなるようにできるのでしょうか。
たしかループは1秒に60回るのですが、countをいれる方法でしょうか?
もしくは、クリックではなく、移動処理時に効果音の処理を組み込むべきでしょうか?
その通りです。連続で鳴ってしまわないように、鳴っていることを示す何らかのフラグあるいはカウンタが必要です。
聞く前に実装してもらったほうが良かったですね。
失敗を恐れたら、ゲームプログラミングで冒険は出来ません。まず聞く前に試すべきです。

ここから色々なエフェクトが入ると思いますが、これが一般的なゲームとしての演出の基本です。
覚えたテクニックは、シューティング、アクションなどで応用出来ますので、やって損なことは何もありませんので考えながら実装しましょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka_taka
記事: 79
登録日時: 11年前

これでいいのでしょうか。

#99

投稿記事 by taka_taka » 11年前

softya(ソフト屋) さんが書きました:UNICODEに対応する書き方をする場合は文字列はTEXT()で統一して下さい。
LoadSoundMem()もTEXT()が必要ですし、charが必要な場所ではcharではなくTCHARで全て書きます。
面倒やらミスが多そうならcharで統一します。その場合は、マルチバイト文字を言語セットとして選択します。
貴重なアドバイスありがとうございます。直しました。

効果音ですが、Puzzle.cppの戻り値を設定し、移動した場合に1、しなかった場合に-1を返す処理にしました。
どうなのでしょうか。
気がかりなのが、main.cpp以外でのエラー発生で、Puzzle.cpp等でのエラーチェックは、,mainと、Puzzle.cppどちらで、
行ったほうがよろしいのでしょうか。
(現在のプログラムは、基本の確認のため、過度のエラーチェックをしていますが、そうした場合のお話になります。)

あと、完成時のエフェクトとシャッフル回数を考えています。

別件なのですが、書き込み字時、コードを書くときに、前後に数十行の改行?が入るのは
取り除く方法はあるのでしょうか?

コード:

/*************************************************************************
* ファイル名   : main.cpp
* プログラム名 : main
* 作成日       : 2013/01/29
* Version      : 1.00
* 概要         : ソフトの実行
* 変更履歴  ;
**************************************************************************/
//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Keyboard.h"
#include "Mouse.h"
#include "Puzzle.h"

/* ************************************** *
 * 関数名 :WINAPI WinMain                *
 * 概要   :ここからプログラムが動き出す  *
 * 戻り値 :0                             *
 * ************************************** */
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

	//MessageBoxの戻り値用変数
	int flag;

	int StringCr;

	//LoadSoundMemの識別番号の格納変数
	int SoHandle;
	
	//ウィンドウモードに変更	
	ChangeWindowMode(true); 

	//DXライブラリ初期化
	if (DxLib_Init() != 0)
	{
		//エラーメッセージを表示
		flag = MessageBox(
                NULL ,
                TEXT("DxLib_Init() err") ,
                TEXT("Err") , 
                MB_OK);
		return -1;
	}

	//マウスカーソルの表示設定フラグのセット マウスカーソルの表示
	if (SetMouseDispFlag( TRUE ) != 0)
	{
		//エラーメッセージを表示
		flag = MessageBox(
				NULL ,
				TEXT("SetMouseDispFlag( TRUE )  err") ,
				TEXT("Err") , 
				MB_OK);
					
		//DXライブラリ使用の終了処理
		DxLib_End();
		return -1;
	}
	
	// 裏画面を使用
	if (SetDrawScreen(DX_SCREEN_BACK) != 0)
	{
		//エラーメッセージを表示
		flag = MessageBox(
				NULL ,
				TEXT("SetDrawScreen(DX_SCREEN_BACK) err") ,
				TEXT("Err") , 
				MB_OK);
					
		//DXライブラリ使用の終了処理
		DxLib_End();
		return -1;
	}

	// 白色の値を取得
	StringCr = GetColor( 255 , 255 , 255 ) ;

	//se_maoudamashii_onepoint25.wavをロードし、識別番号をSoHandleに格納
	SoHandle = LoadSoundMem(TEXT("C:/Documents and Settings/All Users/Documents/My Music/Sample Music/se_maoudamashii_onepoint25.wav"));

	//パズルの初期化
	Puzzle_Initialize();

	while( 1 ){

		// 裏画面の内容を表画面に表示
		if( ScreenFlip() != 0 ){
			//エラーメッセージを表示
			flag = MessageBox(
					NULL ,
					TEXT("ScreenFlip err") ,
					TEXT("Err") , 
					MB_OK);

				break;
		}
		
		//メッセージ処理
		if( ProcessMessage() != 0 ){
			//エラーメッセージを表示
			flag = MessageBox(
					NULL ,
					TEXT("ProcessMessage err(End)") ,
					TEXT("Err") , 
					MB_OK);
	
				break;
		}

		// 画面を初期化
		if( ClearDrawScreen() != 0 ){
			//エラーメッセージを表示
			flag = MessageBox(
					NULL ,
					TEXT("ClearDrawScreen err") ,
					TEXT("Err") , 
					MB_OK);
	
			break;
		}

/*		if( Keyboard_Update() != 0 ){
			flag = MessageBox(
					NULL ,
					TEXT("Keyboard_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			break;
		}	
*/
		//マウスの入力状態更新
		if( Mouse_Update() != 0 ){
			//エラーメッセージを表示
			flag = MessageBox(
					NULL ,
					TEXT("Mouse_Update err") ,
					TEXT("Err") , 
					MB_OK);
	
			break;
		}
		
		//マウス左ボタンが押されているか調べる	
		if( ( Mouse_Get_Input() & MOUSE_INPUT_LEFT ) != 0)
		{
			
			//DrawFormatString( 400, 400, StringCr, "座標 X %d  Y %d", Mouse_Get_X(), Mouse_Get_Y()) ;

		
			//パズルの移動処理
			if (Puzzle_Update(Mouse_Get_X(), Mouse_Get_Y()) == 1) 
			{
				//効果音を出す
				PlaySoundMem( SoHandle, DX_PLAYTYPE_BACK );
			}
		}

		//パズルの描画処理
		Puzzle_Draw();

		//パズルの完成を判定する処理
		if (Puzzle_Differ() == 1)
		{
			//完成の表示
			DrawString( 400, 400, TEXT("完成です!"), StringCr) ;
			break;
		}
	}

	//パズルの終了処理
	Puzzle_Finalize();
	
	//DXライブラリ使用の終了処理
	DxLib_End();

	//ソフトの終了
	return 0;

}

コード:

/*************************************************************************
* ファイル名   : Puzzle.cpp
* プログラム名 : パズル
* 作成日       : 2013/01/29
* Version      : 1.00
* 概要         : パズルの初期化処理、移動処理、完成判定処理、描画処理、終了処理をする
* 変更履歴  ;
**************************************************************************/

//インクルード_dxライブラリ
#include "DxLib.h"

//インクルード_ローカル
#include "Keyboard.h"
#include "Puzzle.h"

//インクルード_標準
#include <stdlib.h>
#include <time.h>

//マクロ
#define BLOCK_SIZE 100
#define PAZZLE_PIECE_NUM 16
#define NUM_BLACKBOX 15

//グローバル変数
static Puzzle_t Puzzle;

//関数定義
/************************************************
宣言	:	swap(int *a, int *b)
概略	:	与えられた二つの引数の値の交換
引数	:	int *a, int *b
戻り値	:	なし
解説	;	与えられた二つのポインタにより、
			呼び出しもとの二つの変数の値を
			入れ替える
*}*********************************************/
void swap(int *a, int *b){
	
	int temp = *a;
	*a = *b;
	*b = temp;
}

/*********************************************************
宣言	:	blackbox_swap(int click_blook_place)
概略	:	blackboxと引数位置のパズルを入れ替える
引数	:	int *a, int *b
戻り値	:	なし
解説	;	blackboxがないか判定、ある場合は
			blackboxと引数のパズルを入れ替える
*}********************************************************/
void blackbox_swap(int click_blook_place){

	int i;

	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
		
		if (Puzzle.Place[i] == click_blook_place)
		{
			//ブラックボックスとの位置を交換する。
			swap(&Puzzle.Place[i], &Puzzle.Place[NUM_BLACKBOX]);
			return;
		}
	}
}
/*********************************************************
宣言	:	Puzzle_Initialize()
概略	:	Puzzle.Place[]の初期化し、シャッフルを行う。
引数	:	なし
戻り値	:	なし
*}********************************************************/
void Puzzle_Initialize(){
	
	int i;
	int a, b;

	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
		Puzzle.Place[i] = i;
	}

	srand((unsigned)time(NULL));
	//シャッフル
	for (i = PAZZLE_PIECE_NUM - 1; i > 1; i--)
	{
		a = i;
		b = rand() % i;
		swap(&Puzzle.Place[a], &Puzzle.Place[b]);
	}

	LoadDivGraph(TEXT("C:/Documents and Settings/All Users/Documents/My Pictures/Sample Pictures/16puzzle01.png"), 16, 4, 4, BLOCK_SIZE, BLOCK_SIZE, Puzzle.GrHandle);
	
}

/************************************************
宣言	:	Puzzle_Update(int MouseX, int MouseY)
概略	:	パズルの移動処理
引数	:	int MouseX, int MouseY
戻り値	:	移動した場合 1
			移動しない場合 -1
*}*********************************************/
int Puzzle_Update(int MouseX, int MouseY){
	
	int click_blook_place;
	
	//パズルの領域内かどうか判定し、位置を求める。
	if (0 <= MouseX && MouseX < 4 * BLOCK_SIZE && 0 <= MouseY && MouseY < 4 * BLOCK_SIZE )
	{
		click_blook_place = MouseX / 100 + MouseY / 100 * 4;
	
	} else {
		return -1;
	}
	
	//クリック場所がブラックボックスの場合、終了処理
	if (click_blook_place == Puzzle.Place[NUM_BLACKBOX]) return -1;

	//クリック場所の上下左右の位置用変数
	int up = 0;
	int down = 0;
	int left = 0;
	int right = 0;

	up = click_blook_place - 4;
	
	//ブラックボックスに該当する場合、交換を行う。
	if (up >= 0 && up == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
		return 1;
	}

	down = click_blook_place + 4;

	//ブラックボックスに該当する場合、交換を行う。
	if (down >= 0 && down == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
		return 1;
	}

	if (click_blook_place % 4 == 0)left = -1;
	else left = click_blook_place - 1;

	//ブラックボックスが該当する場合、交換を行う。
	if (left >= 0 && left == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
		return 1;
	}

	if (click_blook_place % 4 == 3)right = -1;
	else right = click_blook_place + 1;

	//ブラックボックスが該当する場合、交換を行う。
	if (right >= 0 && right == Puzzle.Place[NUM_BLACKBOX])
	{
		blackbox_swap(click_blook_place);
		return 1;
	}
	
	return -1;
}

/************************************************
宣言 : Puzzle_Differ()
概略 : パズルの完成判定処理
引数 : なし
戻り値: int型   1 :完成
     int型 -1 :未完成
*}*********************************************/
int Puzzle_Differ(){
 
    int i;
    int ok = 1;
 
    int white = GetColor( 255 , 255 , 255 );
	
	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
    {
        ////Puzzle.Place[]が元の位置の配置になっているかを判定し、配置が異なる場合はOKを0にする
        if (Puzzle.Place[i] != i) 
        {
            ok = 0;
        }
    }
 
    if (ok == 1) {
        return 1;
    }
    return 0;
}

/************************************************
宣言 : Puzzle_Draw()
概略 : パズルの描画処理
引数 : なし
戻り値:  なし
*}*********************************************/	
void Puzzle_Draw(){
	int i;

	//ブラックボックスでなければ、Puzzle.Place[]の位置で、パズル1から15を描画する
	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
		if (i != NUM_BLACKBOX)
		{
			DrawGraph( BLOCK_SIZE * (Puzzle.Place[i] % 4), BLOCK_SIZE * (Puzzle.Place[i]/4), Puzzle.GrHandle[i], FALSE);
		}
	}
}

/************************************************
宣言 : Puzzle_Draw()
概略 : パズルの終了処理
引数 : なし
戻り値:  なし
*}*********************************************/
void Puzzle_Finalize(){
	
	int i;
	
	for (i = 0; i < PAZZLE_PIECE_NUM; i++)
	{
		DeleteGraph(Puzzle.GrHandle[i]);
	}
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 初心者が15パズル作成するのは、難しいでしょうか。

#100

投稿記事 by softya(ソフト屋) » 11年前

処理的には、戻り値で効果音を処理するより、入れ替えが発生した場所で効果音を鳴らすべきだと思います。
つまり、効果音専用のソースファイルを作って関数を呼ぶだけで鳴らす様にしたほうが良いと思います。

>あと、完成時のエフェクトとシャッフル回数を考えています。

入れ替え時のエフェクトとか、マウスが指しているパーツのハイライトやら縁が白く光るなども欲しいですね。

>別件なのですが、書き込み字時、コードを書くときに、前後に数十行の改行?が入るのは
>取り除く方法はあるのでしょうか?

これに関しては意味が良く分かりません。
どういう操作で起こるのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る