質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

1265閲覧

キャラクターの現在位置の値が入りません。

mikamikan

総合スコア16

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2015/11/23 21:01

###前提・実現したいこと
将来的にゲームを作りたいと思っています。
そのため、まずC言語でキーボード入力でキャラクターの座標を動かすプログラムを作成しようと思いました。
###発生している問題・エラーメッセージ
数字の0,1,2,それ以外で上下左右の方向に移動するように割り当てたのですが、どの数字をキーボードで入力してもxy座標が(75,-25)になってしまい、なおかつ変わりません。

ここで行き詰ってしまったので、ぜひ皆さんの知恵を貸してください!

###ソースコード

C

1#define _CRT_SECURE_NO_WARNINGS 2#include <stdio.h> 3#include <stdlib.h> 4#include <time.h> 5#define _USE_MATH_DEFINES 6#include <math.h> 7 8typedef struct car { 9 int x; //現在位置x 10 int y; //現在位置y 11 double max_x; //xの最大値 12 double max_y; //yの最大値 13 int L = 50; 14}car; 15 16int move(car car, int a, int area); 17 18int main() { 19 FILE *file; 20 file = fopen("car.csv", "w"); 21 car car; 22 23 int num_step; //ステップ数 24 int j; 25 int a, sd; 26 int area; 27 28 int reward; 29 30 int num_a; //行動 31 int num_s; //状態 32 33 34 car.max_x = 250; 35 car.max_y = 250; 36 num_a = 4; 37 38 //エリアの数 39 num_s = 25; 40 41 //初期設定 42 car.x = 25; 43 car.y = 25; 44 area = car.x / 50 + car.y / 50 * 5; 45 46 for (j = 0; j < 10; j++) { 47 fprintf(file, "j=%d\n", j); 48 49 scanf("%d", &a); 50 sd = move(car, a, area); 51 52 //ここで障害物の設定 53 //障害物があるareaに入るとrewardに-10が入り試行を終了する 54 //Goalに入るとrewardに+10が入り試行を終了 55 //その他はreward=0なのでそのまま続行 56 if (area = 24) { 57 reward = 10; 58 } 59 else if (area = 5 || 8 || 13 || 22) { 60 reward = -10; 61 } 62 else { 63 reward = 0; 64 } 65 //もしxとyが環境の範囲からでたらreward=-1を入れる 66 if (car.x < 0 || car.max_x < car.x || car.y < 0 || car.max_y < car.y) { 67 reward = -1; 68 } 69 70 if (reward < 0) { 71 //失敗 72 car.x = 0; 73 car.y = 0; 74 area = car.x / 50 + car.y / 50 * 5; 75 break; 76 } 77 else if (reward < 0) { 78 79 //成功 80 car.x = 0; 81 car.y = 0; 82 area = car.x / 50 + car.y / 50 * 5; 83 break; 84 } 85 else { 86 //続行 87 area = sd; 88 }fprintf(file, "%d,%d,%d,%d,%d\n", car.x, car.y, a, sd, area); 89 } 90 fclose(file); 91 return 0; 92} 93 94int move(car car, int a,int area) { 95 if (a = 0) { 96 car.y = car.y + 50; 97 } 98 if (a = 1) { 99 car.x = car.x + 50; 100 } 101 if (a = 2) { 102 car.y = car.y - 50; 103 } 104 else { 105 car.x = car.x - 50; 106 } 107 108 printf("%d,%d\n", car.x, car.y); 109 int sd; 110 //sdはアクションが起こった後のareaを表す 111 sd = car.x / 50 + car.y / 50 * 5; 112 113 return area; 114}

###補足情報(言語/FW/ツール等のバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

一つの原因は、関数 int move(car car, int a,int area) 内の比較式が誤っていることが原因と思います。

int move(car car, int a,int area) { if (a = 0) { car.y = car.y + 50; } if (a = 1) { car.x = car.x + 50; } if (a = 2) { car.y = car.y - 50; } else { car.x = car.x - 50; }

おそらく使用したい演算子は代入演算子の = ではなく、比較演算子は == ではないですか?

ex.)
if (a == 0) {


この場合、比較式ではなく記述された代入式の値が0かどうかで偽か真かが決まります。

if (a = 0) の式 a = 0 の結果は 0 ですので、条件式は常に成立しません。
if (a = 1) の式 a = 1 の結果は 1 ですので、条件式は常に成立します。
if (a = 2) の式 a = 2 の結果は 2 ですので、条件式は常に成立します。

つまり move は a の値にかかわらず、呼び出されるたびに

car.x = car.x + 50;
car.y = car.y - 50;

が実行されてしまっています


その後、追記

他も見てみると、if 文の比較式の記述が、かなり誤っているみたいです。

if (area = 24) { ← 常に真になる   

     ↓
if (area == 24) {

else if (area = 5 || 8 || 13 || 22) {   ← 常に真になる

     ↓
else if ((area == 5) || (area == 8) || (area ==13) || (area ==22)) {
自分なら switch(area) を使いますけど…

投稿2015/11/23 21:28

編集2015/11/23 21:59
T.Kanno

総合スコア915

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mikamikan

2015/11/24 12:09

回答ありがとうございます! =の使い方、思いっきり間違っていたので勉強になりました。 本当にありがとうございました!
guest

0

=についてはT.Kannoさんのご指摘通りです。初心者は間違えやすいので気をつけましょう。

もう一つ重要な問題点があります。
int move(car car, int a, int area)
構造体の変数が「値渡し」になっています。これではmove関数内でcar変数を変更しても、呼び出し元には反映されません。

この場合、C言語では「ポインタ渡し」をする必要があり、このように書きます。
int move(car *car, int a, int area)

呼び出し側は
sd = move(&car, a, area);
このように変数名に&を付けることでポインタが渡されるようになります。

move関数内でcar変数の値を取得したり設定したりする際は、
car->y = car->y + 50;
このように.ではなく->でメンバ変数をつなげます。

それと、構造体名とtypedefによる別名、そして変数名をどれも同じ名前にしているので判りづらくなっています。区別が付くような名前を付けた方がいいでしょう。

追加でもう一点。
move関数のreturnがareaとなっていますが、sdの間違いでは?

投稿2015/11/24 02:35

編集2015/11/24 02:45
catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mikamikan

2015/11/24 12:11

回答ありがとうございます! 値が反映されない謎は値渡しをしていたからだったんですね。 とても参考になりました。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問