All posts by chen

C# exercises (7) Puzzle Game

今回作るのは、イメージを読み込んで利用するパズルゲームです。イメージファイルを読み込むとそれを 9 分割し、ランダムに混ぜます。

プレビューのイメージをフォーム上クリックして配置、すべて正しい場所に配置できればクリアです。

PuzzleGame3x3

 

フォーム作成

サイズ:500 x 400

背景色:適当

スクリーンショット 2016-06-03 10.47.38

PictureBox配置

  • (Name) : PlayBox
  • Size :        300 x 300
  • BackColor :  white

プレビュー用PictureBox配置

  • (Name) : Preview
  • Size :        100 x 100
  • BackColor :  white

スクリーンショット 2016-06-03 10.56.11

 

 

メニュー作成

MenuStrip をフォームにドロップ、下記のようにメニュー追加

  • File
    • Load Image…

 

スクリーンショット 2016-06-03 10.59.28

 

ダイアログ作成

openFileDialog をフォームにドロップ、フィルターを設定

  • Image Files (*.png, *.jpg) | *.png; *.jpg

スクリーンショット 2016-06-03 11.09.08

 

イベント設定

PlayBox

  • MouseDown : PlayBox_MouseDown
  • Paint : PlayBox_Paint

Preview

  • Paint : Preview_Paint

LoadImage

  • Click : LoadImage_Click

スクリーンショット 2016-06-03 11.15.29

 

ソースコード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace PuzzleApp
{
    public partial class Form1 : Form
    {
        // ゲームで使う変数(フィールド)
        Image img = null;
        bool[] flg = new bool[9];
        int[] data = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
        int[] answer = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
        int current = 0;
        bool playflg = false;
        bool clearflg = false;


        public Form1()
        {
            InitializeComponent();
        }


        // 変数関係の初期化処理
        private void initialData()
        {
            flg = new bool[9];
            data = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
            answer = new int[] { -1, -1, -1, -1, -1, -1, -1, -1, -1 };
            Random r = new Random(Environment.TickCount);
            for (int i = 0; i < 100; i++)
            {
                int a = r.Next(9);
                int b = r.Next(9);
                int n = data[a];
                data[a] = data[b];
                data[b] = n;
            }
            current = 0;
            playflg = true;
            clearflg = false;
        }


        // クリアしたかどうかをチェック
        private void checkClear()
        {
            bool flg = true;
            for (int i = 0; i < 9; i++)
            {
                if (answer[i] != i) { flg = false; }
            }
            clearflg = flg;
        }


        // ゲームが終わったかどうかチェック
        private void checkGameEnd()
        {
            bool flg = false;
            for (int i = 0; i < 9; i++)
            {
                if (answer[i] == -1) { flg = true; }
            }
            playflg = flg;
            if (playflg == false)
            {
                this.checkClear();
            }
        }


        // オープンダイアログを開いてイメージファイルをロードする
        private void LoadImage_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
            {
                img = Image.FromFile(openFileDialog1.FileName);
                this.initialData();
                this.Refresh();
            }
        }


        // PlayBoxの表示
        private void PlayBox_Paint(object sender, PaintEventArgs e)
        {
            if (img == null) { return; }
            Graphics g = e.Graphics;
            for (int i = 0; i < 9; i++)
            {
                if (flg[i] == false) { continue; }
                if (answer[i] == -1) { continue; }
                int x1 = i % 3;
                int y1 = i / 3;
                int x2 = answer[i] % 3;
                int y2 = answer[i] / 3;
                Rectangle r1 = new Rectangle(100 * x1, 100 * y1, 100, 100);
                Rectangle r2 = new Rectangle(100 * x2, 100 * y2, 100, 100);
                g.DrawImage(img, r1, r2, GraphicsUnit.Pixel);
            }
            if (playflg == false)
            {
                if (clearflg)
                {
                    g.DrawString("CLEAR!!",
                        new Font("Impact", 48, FontStyle.Bold),
                        new SolidBrush(Color.Red),
                        new Point(40, 100));
                }
                else
                {
                    g.DrawString("GAMEOVER...",
                        new Font("Impact", 36, FontStyle.Bold),
                        new SolidBrush(Color.Blue),
                        new Point(20, 200));
                }
            }
        }


        // PlayBoxをクリックした時の処理
        private void PlayBox_MouseDown(object sender, MouseEventArgs e)
        {
            if (playflg == false) { return; }
            if (img == null) { return; }
            if (current > 8) { return; }
            int x = e.X / 100;
            int y = e.Y / 100;
            if (x < 0) { return; }
            if (y < 0) { return; }
            if (x >= 3) { return; }
            if (y >= 3) { return; }


            int n = x + y * 3;
            flg[n] = true;
            answer[n] = data[current];
            current++;
            this.checkGameEnd();
            this.Refresh();
        }


        // previewの表示
        private void Preview_Paint(object sender, PaintEventArgs e)
        {
            if (img == null) { return; }
            if (current > 8) { return; }
            int x = data[current] % 3;
            int y = data[current] / 3;
            Graphics g = e.Graphics;
            Rectangle r1 = new Rectangle(0, 0, 100, 100);
            Rectangle r2 = new Rectangle(x * 100, y * 100, 100, 100);
            g.DrawImage(img, r1, r2, GraphicsUnit.Pixel);
        }
    }
}

 

実行結果

 

スクリーンショット 2016-06-03 11.30.31

 

スクリーンショット 2016-06-03 11.29.42

参考

http://www18.big.or.jp/~neon2/bunkatu/tips9.shtml

C programming (8) if statement

 

制御構文は、上から下へ流れるプログラムを途中で流れを分岐させたり、流れを繰り返したりすることができる構文を表します。

制御構文の主な種類としてif文for文while文switch文の4パターンあります。

if文を使うと、分岐構造を作ることができます。

条件式の真偽

状態 真偽
条件が満たされた場合 true(真) 1(0以外)
条件が満たされなかった場合 false(偽) 0

 関係演算子

2つの値の大小を比較します。
条件を満たせば「真(true)」、条件を満たさなければ「偽(false)」となります。
関係演算子の形式は以下の通りです。

演算子 意味
< a < b aはbよりも小さい
> a > b aはbよりも大きい
<= a <= b aはbよりも小さい(a == bの条件も含む)
>= a >= b aはbよりも大きい(a == bの条件も含む)
== a == b aとbは等しい
!= a != b aとbは等しくない

if 文

if文の基本形

条件式には真、又は偽を表す値(すなわち、最終的には数値型)を指定します。if 文は条件式の結果が真の場合のみ実行され、そうでなければ実行されません。より単純にいえば、条件式に 0 以外の値が指定されたときのみ実行されるのです。

if(条件式) {
    文1;
}

 

if  ~ else ~

if(条件式) {
    文1;
} else {
    文2;
}

実例: 偶数奇数判定

/* a5-1-4.c */
#include <stdio.h>

int main(void)
{
  int n;
  printf("整数値を入力してください。> ");
  scanf("%d", &n);
  if (n % 2 == 0) { 
      printf("入力値は偶数です。\n");  
  } else {
      printf("入力値は奇数です。\n");
  }

  printf("プログラムのおわり\n");
  getch();
  return 0;
}

 

if文の多分岐構造

if(条件式1) {
    文1;
} else if(条件式2) {
    文2;
} else if(条件...
:
(中略)
:
} else if(条件式n) {
    文n;
} else {
    文x;
}

実例:成績判定

/* 成績判定プログラム */
#include <stdio.h>
// C判定:ten 60以上69以下  不合格:ten 59以下 

int main(void)
{
  int ten;
 while (1) //ブロック
 {
  printf("点数を入力してください。> ");
  scanf("%d", &ten);
  if ( ten == 0 ) break;
             // OR 
  if (ten < 0 || ten > 100) {  // ペアー
    printf("点数の入力エラーです。\n");
  }
  else 
  if (ten >= 80) {  // block ブロック
    printf("成績はA判定です。\n"); 
  }
  else if (ten >= 70) {
    printf("成績はB判定です。\n");
  }
  else {
    printf("成績はC判定です。\n");
  }
 }
    getch();
  return 0;
}

 

if文のネスト

if(条件文1) {
    if(条件文2) {
        文1;
    } else {
        文2;
    }
} else {
    文3;
}

実例:出席率と点数から成績を判定

/* 出席率と点数から成績を判定するプログラム */
#include <stdio.h>
// nest 入れ子
int main(void)
{
  int ten, percent;
while (1)   // ブロック block
{
  printf("授業の出席率は何%ですか。> ");
  scanf("%d", &percent);
     
  if (percent >= 80) 
  {
    printf("点数は何点ですか。> ");
    scanf("%d", &ten);    // 入れ子 nest
    if (ten >= 60)  
    {
      printf("合格です。\n");
    }
    else 
    {
      printf("再試験です。\n");
    }
  }  //ペアー 
  else {
    printf("補習です。\n");
     }
}		 

  return 0;
}

 演習問題

演習3-4 (教科書P51)

二つの整数値を読み込んで、値の関係を表示するプログラムを作成

  • 「AとBは等しいです。」
  • 「AはBより大きいです。」
  • 「AはBより小さいです。」

実行例

二つの整数を入力してください。
整数A:12
整数B:6
AはBより大きいです。

 

C exercises(7) Pointer Arrays

ポインタの配列

複数の文字列をchar型の2次元配列で宣言しました。それを下記に示します。

char kw[3][7] = {"double", "extern", "switch"};

同様なものをポインタを使って宣言すると、下記のようにポインタの配列となります。

const static char *wday[  ] = {
    "Sunday", 
    "Monday", 
    "Tuesday",
    "Wednesday", 
    "Thursday",
    "Friday", 
    "Saturday", 
    NULL
};

[ ]の中には8が入るのですが、コンパイラが数えてくれるので省略しています。

wday[0]は最初は”Sunday”の先頭アドレスを指します。
wday[1]は最初は”Monday”の先頭アドレスを指します。
wday[0]++とすると、
wday[0]は”Sunday”の1番目の要素を指します。
wday[1]++とすると、
wday[1]は”Monday の2番目の要素を指します。

以下、同様です。

配列の最後の要素は、’NULL’です。このようにしてあるのは、ポインタの配列が幾つあるか計るためです。

‘NULL’を使わない場合は、ポインタの配列の数を保持している変数が必要になります。

#include <stdio.h>

  /* ポインタwday[  ]の指している文字列の配列は、
     const:書き変え禁止で
     static:他のファイルから参照禁止 */

const static char *wday[  ] = {
    "Sunday", 
    "Monday", 
    "Tuesday",
    "Wednesday", 
    "Thursday",
    "Friday", 
    "Saturday", 
    NULL
};

void MyPrint(const char **p);  /* 引数はポインタを指すポインタ */
void main(void);

void MyPrint(const char **p)
{
    while (*p) {               /* pの指すポインタがNULLでない間 */
        printf("%s\n", *p);    /* pの指す中身を表示 */
        p++;
    }
    printf("\n");
}

void main(void)
{
    const char **p;      /* ポインタを指すポインタ */

    p = wday;            /* ポインタの配列の先頭を指すようにする */
    MyPrint(p);

    while (*wday[0] != '\0' )        /* 指す中身がNULLでない間 */
        printf("%c ", *wday[0]++ );  /* 表示する */
    printf("\n");
}

出力結果

Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday

S u n d a y

演習

A7-4-2 (P253)

疑似乱数を発生させ、「誰がいつとこで何をした」と表示してください。

(Who) が (When)  (Where) で (What) をした。

ヒント

  printf("%s が %s %s で %s をした", 
    pwho[rand() % 3], 
    pwhen[rand() % 3],
    pwhere[rand() % 2],
    pwhat[rand() % 2]
  );

出力結果

田中が夜家で勉強をした。

 

C# exercises (6) Graphics and Paint

Graphicsオブジェクト

ウインドウの内部を表示したり描き直したりする必要が生ずると、Formに「Paint」というイベントが発生し、Paintプロパティに設定されているメソッドが呼び出されるようになっています。

このPaintイベント用のメソッドは、これまでのクリック時のイベント用メソッドなどとは微妙に違いがあります。これは以下のように定義されます。

private void メソッド名 (object sender, PaintEventArgs e)
{
    ……ここに描画処理を書く……
}

第1引数に、イベントが発生したオブジェクトが渡されるのは同じですが、第2引数に渡されるのはSystem.Windows.Formsパッケージの「PaintEventArgs」というクラスのインスタンスです。これは、描画のためのイベント情報を管理するもので、描画に必要なオブジェクトなどもこの中にまとめられているのです。
中でも重要なのが「Graphics」というオブジェクトです。これはSystem.Drawingパッケージに用意されているクラスで、これはGDI+(Graphics Device Interfaceというグラフィック描画のための機能の強化版)を利用して画面にさまざまな描画を行うための機能を提供します。

Paintイベント

フォームのプロパティをイベントに切り替えて、Paintイベントを探し、メソッド名Form1Paintを入力

スクリーンショット 2016-05-27 11.31.11

Paintイベントで渡されるPaintEventArgsインスタンスから以下のようにして取り出します。

Graphics 変数 = 《PaintEventArgs》.Graphics;

Penと図形の描画

  • g.DrawLine(p,75,75,50,50);  // 直線
  • g.DrawEllipse(p,75,75,50,50);  // 円
private void Form1Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    Pen p = new Pen(Color.Red); // Penインスタンスの作成
    g.DrawEllipse(p,75,75,50,50);
}

Penと多角形を描く

private void Form1Paint(object sender, PaintEventArgs e)
{
 Graphics g = e.Graphics;
 Pen p = new Pen(Color.Red); // Penインスタンスの作成
 Brush b = new SolidBrush(Color.Blue); // Brushインスタンスの作成

 //直線で接続する点の配列を作成
 Point[] ps = {new Point(100, 0),
     new Point(158, 180),
     new Point(4, 69),
     new

Point(195,

 69),
     new Point(41, 180)};
 //多角形を描画する
 g.DrawPolygon(p, ps);
}

 

Brushと塗りつぶし図形

private void Form1Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    Brush b = new SolidBrush(Color.Blue); // Brushインスタンスの作成
    g.DrawEllipse(p,75,75,50,50);
}

実例

using System;
using System.Drawing;
using System.Windows.Forms;
 
namespace MyFrmApp
{
    public class MyForm : Form
    {
             
        public MyForm()
        {
            this.Width = 300;
            this.Height = 200;
            this.Paint += myframe_paint;
        }
             
        private void Form1Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Pen p = new Pen(Color.Red); // Penインスタンスの作成
            Brush b = new SolidBrush(Color.Blue); // Brushインスタンスの作成
            g.FillRectangle(b,50,50,50,50);
            g.DrawEllipse(p,75,75,50,50);


            //直線で接続する点の配列を作成
            Point[] ps = {new Point(0, 0),
            new Point(150, 50),
            new Point(80, 100),
            new Point(100, 150)};
            //多角形を描画する
            g.DrawPolygon(p, ps);
        }
    }
}

スクリーンショット 2016-05-27 11.29.37

演習

五芒星を描く

220px-Pentagram.svg

star

***

五芒星(ごぼうせい、英: pentagram)または五芒星形・五角形・型・型五角形・正5/2角形は、互いに交差する、長さの等しい5本の線分から構成される図形で型正多角形の一種である。 正五角形に内接し、対称的である。 一筆書きが可能。

 

middle_1310314010

Pentacle_2.svg

 参考

  • http://qiita.com/tomato360/items/a59f2ee4df4fd2f24227

C programming (7) Ch1 & Ch2 Summary

履修システム使い方

(塚本先生担当)

連絡事項

花やしきについて、学生にお知らせ頂きたい事項を3点連絡

 ①遅刻しないように 9:20までに 161教室に集合する事
  出席の確認をします。
 ②着物着付け、忍者の時間割をお知らせします。
  「誰が何時」という情報
 ③雨が降っても花やしきに行きます。
  必ず9:20までに161教室に登校する事

 

第一章、第二章のまとめ

過去のページを参照

演習

演習2-6(P37)

身長を整数値として読み込み、標準体重を実数で表示するプログラムを作成せよ。

標準体重 = (身長 – 100) * 0.9

実行例

身長を入力してください: 175
標準体重は 67.5 です

 

C exercises(6) Pointers and Variables

ポインタの仕組み:ポインタで変数を指す

ポインタとは

ポインタ (pointer)とは、あるオブジェクトがなんらかの論理的位置情報でアクセスできるとき、それを参照するものである。有名な例としてはC/C++でのメモリアドレスを表すポインタが挙げられる。(ja.wikipedia.org)

ポインタ=メモリアドレス

間接演算子 * と アドレス演算子 &

ポインタの使用手順

  1. 宣言
  2. アドレスの設定
  3. 使用

ポインタで変数

間接演算子を使って、ポインタが指すメモリの値を取得することを間接参照するといいます。

間接演算子を用いれば、アドレスを間接参照するだけではなく、ポインタが表すアドレスに値を間接代入することもできます。

#include <stdio.h>

int main() {
  int iVar = 0;
  int *iPo = &iVar;   // 宣言&設定

  printf("*iPo = %d\n" , *iPo);  // 使用

  *iPo = 100; // 間接代入
  printf("iVar = %d\n" , iVar);
  return 0;
}

 

ポインタで配列

配列とポインタは全く別物

配列とは、多数の変数を順番つけでまとめて扱う方法であり、
ポインタとは、変数のショートカットを作る方法です。

文字列を1文字ずつ表示するプログラム

/* 文字列を1文字ずつ表示するプログラム */
#include <stdio.h>

int main(void)
{
  char str[] = "sun";
  char *p;  // 宣言

  p = str;  // 設定
  
  while (*p != '\0') {
    printf("%c ", *p);
    p++;
  }

  return 0;
}

 

演習(P245-2)

str1 に、’ABCDEFGHIJKLMNOPQRSTUVWXYZ’と初期化
str2 に文字列を逆順に格納

コード: a7-2-3.c

実行結果例: a7-2-3.exe

str1 = ABCDEFGHIJKLMNOPQRSTUVWXYZ
str2 = ZYXWVUTSRQPONMLKJIHGFEDCBA

C programming (6) type and conversions

型と型変換

  • int — 整数
  • double — 浮動小数点数

平均点を求めるプログラム

#include <stdio.h>
 
int main(int argc, const char * argv[])
{
     
    // insert code here...
    int score[5];       // 5人の点数を入れる配列
    int sum;            // 合計点
     
    // 各点数を入れる
    score[0] = 77;
    score[1] = 80;
    score[2] = 65;
    score[3] = 60;
    score[4] = 70;
     
    // 各点数を全て足して合計点を求める
    sum = score[0] + score[1] + score[2] + score[3] + score[4];
     
    // 平均点を表示する
    printf("平均点は%d点です。", sum / 5);
     
    return 0;
}

正しい結果は70.4

しかしプログラムは平均点は70点と表示され、一部情報を失ってしまう。

sum  / 5  = 70  (余り 2)

型と演算

算術変換

オペランドは、式の中でよりサイズの大きい型に合わせて変換されるというお約束があります。(暗黙的な型変換

もし、サイズの大きい型を小さい型に変換した場合、上位ビットを切り捨てることになるため、情報を失ってしまう可能性があります。しかし、サイズを拡張する場合は情報を失うことはありません。

211.1

sum  / 5  = 70

sum  / 5.0  = 70.4

#include <stdio.h>
 
int main(int argc, const char * argv[])
{
     
    // insert code here...
    int score[5];       // 5人の点数を入れる配列
    int sum;            // 合計点
     
    // 各点数を入れる
    score[0] = 77;
    score[1] = 80;
    score[2] = 65;
    score[3] = 60;
    score[4] = 70;
     
    // 各点数を全て足して合計点を求める
    sum = score[0] + score[1] + score[2] + score[3] + score[4];
     
    // 平均点を表示する
    printf("平均点は%f点です。", sum / 5.0);
     
    return 0;
}

 

代入変換

代入の場合も、型が異なる場合は暗黙的に変換して代入されます。これを代入変換と呼びます。

  • 拡張変換
  • 縮小変換 (情報一部損失)
    • 整数から整数の場合、上位ビットが切り捨て
    • 浮動小数点数から整数の場合、小数部の情報が失われ

 

#include <stdio.h>
 
int main(int argc, const char * argv[])
{
     
    // insert code here...
    int score[5];       // 5人の点数を入れる配列
    double sum;            // 合計点
     
    // 各点数を入れる
    score[0] = 77;
    score[1] = 80;
    score[2] = 65;
    score[3] = 60;
    score[4] = 70;
     
    // 各点数を全て足して合計点を求める
    sum = score[0] + score[1] + score[2] + score[3] + score[4];
     
    // 平均点を表示する
    printf("平均点は%f点です。", sum / 5);
     
    return 0;
}

 

型キャスト変換

指定した型に値を変換するようにプログラマが伝える明示的な変換方法も存在します。これを型キャスト変換と呼びます。

(変換型名)

sum  / 5  = 70

(double) sum  / 5  = 70.4

#include <stdio.h>
 
int main(int argc, const char * argv[])
{
     
    // insert code here...
    int score[5];       // 5人の点数を入れる配列
    int sum;            // 合計点
     
    // 各点数を入れる
    score[0] = 77;
    score[1] = 80;
    score[2] = 65;
    score[3] = 60;
    score[4] = 70;
     
    // 各点数を全て足して合計点を求める
    sum = score[0] + score[1] + score[2] + score[3] + score[4];
     
    // 平均点を表示する
    printf("平均点は%f点です。", (double)sum / 5);
     
    return 0;
}

演習課題

型キャストを利用して浮動小数点型変数 から実数や小数を取り出す

出力例:

浮動小数点数 = 12.34
実数 = 12
小数 = 0.34

解答例:

#include <stdio.h>

int main()
{
  float fVar = 12.34f;

  printf("全体 = %g\n" , fVar);
  printf("実数 = %d\n" , (int)fVar);
  printf("小数 = %g\n" , fVar - (int)fVar);

  return 0;
}

 

C exercises(5) Address

ポインタの仕組み:アドレスとは

ポインタはC言語(および拡張言語)に特有の概念で、C言語を学び始めた初心者が必ずといっていいほどつまづく概念でもあります。ポインタがどうしても理解できないためにC言語に挫折してしまう方もいます。

p

アドレスの基本

コンピュータの記憶装置(メモリ)には、アドレスが付けられている。

shikumi

変数のアドレス

変数のアドレスを取得するには変数名の前にアンパサンド “&”をつけます。

int a = 123;

printf(“aのアドレス : %p\n”, &a);

配列のアドレス

配列の先頭をアドレスは、配列名だけで示します。要素のアドレスは&配列名[添字]で示します。

#include <stdio.h>

int main()
{
  char str[3] = "AB";

  printf("str[0]の要素のアドレス: %p\n", &str[0]);
  printf("strのアドレス: %p\n", str);

  getch();
  return 0;
}

 

 

二次元配列のアドレス

二次元配列の先頭アドレスは、配列名だけで示します。要素のアドレスは&配列名[行][列]で示します。

値とアドレスの表現

変数、1次元配列、2次元配列の整理

(要素)アドレス 先頭アドレス
変数 変数名 &変数名
1次元配列 配列名[添字] &配列名[添字] 配列名
2次元配列 配列名[行][列] &配列名[行][列] 配列名

 

printf と scanf の引数とアドレス

「値渡し」

int a = 10;
int str[] = "DEF";

printf("%d", a);  // 値渡し
printf("%s", str); // 参照渡し

 

「参照渡し」

int a;
int str[100];

scanf("%d", &a);
scanf("%s", str);

 

演習(P231)

一次元配列とそれぞれの要素のアドレスを表示するプログラムを作成

str[0]の要素の値        : 'A'
str[1]の要素の値        : 'B'
str[2]の要素の値        : 0x0 // 16進数で出力する
str[2]の要素の値        : ' '
str[0]の要素のアドレス  : 0019FF49
str[1]の要素のアドレス  : 0019FF4A
str[2]の要素のアドレス  : 0019FF4B
strの先頭要素のアドレス : 0019FF49

 

[GCC]C Compiler on MacBook

MacBookで、C言語開発環境の構築

Macに最初から入っている「テキストエディット」とMacに最初から入っている「ターミナル」から入門できますが、無料で多機能AtomVSCodeを使えこなせるとより本格的にC言語開発できます。

Mac:C言語開発環境

Xcode またはXcode Command Line Toolsを入れる。

Xcode

MacBookでは、Xcodeの開発環境を入れるは普通だか、サイズが大きい。iPhoneのアプリ開発環境も一気に揃う利点があります。

Xcode Command Line Tools

Xcode Command Line Toolsだけ入れるとする。サイズの節約になります。

# xcode-select –install

上記コマンド打って「インストール」を選択するだけでいい!

インストールしたら、確認する:
chen-no-air:bin chen$ gcc --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.4.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
chen-no-air:bin chen$
chen-no-air:bin chen$ git --version
git version 2.6.4 (Apple Git-63)
chen-no-air:bin chen$
Mac: ソースコード作成

Macに最初から入っている「テキストエディット」, 「ターミナル」で使えるVimや無料で多機能AtomVSCodeなどのテキストエディタを使って、以下のプログラムをhello.cというファイル名で作成します。作成したファイルはデスクトップに保存します。

#include<stdio.h>
int main() {
  printf("Hello, World\n");
  return 0;
}

Mac:ソースコードコンパイル(gcc)

次に「Finder」を起動し、「アプリケーション」→「ユーティリティ」から「ターミナル」を起動します。

cdコマンドで作業ディレクトリをデスクトップに移動します。

$ cd ~/Desktop/

gccコマンドで、実行ファイルを指定して、hello.cをコンパイルします。

$ gcc hello.c -o hello

そしたら hello が作られています。

Mac:プログラムの実行

指定した実行ファイルを入力し、プログラムを実行します。

$ ./hello 
Hello, World

無事に実行できました。

参考

  • http://matome.naver.jp/odai/2135755970513071001 — 【Hello World!】MacでC言語プログラミングの勉強をするための準備〜【超初心者】
  • http://www.yoheim.net/blog.php?q=20111218 — [C言語] MacbookでC言語を学習する環境を作る方法
  • http://dotinstall.com/lessons/basic_c — C言語の基礎 (全22回) – ドットインストール

C# exercises (5) Calculator

my電卓を作ろう

逆ポーランド記法電卓

Reverse Polish Notation Calculator

画面をデザインする

スクリーンショット 2016-05-02 16.20.21

ツールボックスの中で、

  • コモンコントロール「TextBox」
    • TextBox –>  (name): typeText;  text: 0
    • TextBox –> (name): lastText;  text: 0
  • コモンコントロール「Button」
    • Button1 –> (name): plusButton;  text: +
    • Button2 –> (name): subButton; text: –
    • Button3 –> (name): multiButton; text: x
    • Button4 –> (name): divButton; text: /
    • Button5 –> (name): clrButton; text: CL
    • Button6 –> (name): enterButton; text: ER

Formにドラッグ&ドロップする

プログラミング

KeyPressイベントを作成

Form1を選択し、Form1のイベントの表示に切り替えて、「KeyPress」イベントに、FormKeyPressを入力

スクリーンショット 2016-05-02 16.23.53

FormKeyPressメソッドを作成

六つボタンを選択した状態で、コントロール類の、「KeyPress」イベントに、FormKeyPressimageを選択。

スクリーンショット 2016-05-02 16.28.36

private void FormKeyPress(object sender, KeyPressEventArgs e)
{
    string key = e.KeyChar.ToString();
    int n = 0;
    try
    {
        n = int.Parse(key);
    }
    catch
    {
        return;
    }
    string num = typeText.Text + n;
    try
    {
        typeText.Text = "" + int.Parse(num);
    }
    catch
    {
        return;
    }
}

plusButtonClickメソッドを作成

スクリーンショット 2016-05-02 16.41.55

private void plusButtonClick(object sender, EventArgs e)
{
    try
    {
        int lastnum = int.Parse(lastText.Text);
        int typenum = int.Parse(typeText.Text);
        lastText.Text = "" + (lastnum + typenum);
        typeText.Text = "0";
    }
    catch
    {
        return;
    }
}

subButtonClickメソッドを作成

スクリーンショット 2016-05-02 16.42.20

private void subButtonClick(object sender, EventArgs e)
{
   try
   {
       int lastnum = int.Parse(lastText.Text);
       int typenum = int.Parse(typeText.Text);
       lastText.Text = "" + (lastnum - typenum);
       typeText.Text = "0";
   }
   catch
   {
       return;
   }
}

multiButtonClickメソッドを作成

スクリーンショット 2016-05-02 16.43.30

private void multiButtonClick(object sender, EventArgs e)
{
    try
    {
        int lastnum = int.Parse(lastText.Text);
        int typenum = int.Parse(typeText.Text);
        lastText.Text = "" + (lastnum * typenum);
        typeText.Text = "0";
    }
    catch
    {
        return;
    }
}

divButtonClickメソッドを作成

スクリーンショット 2016-05-02 16.44.14

private void divButtonClick(object sender, EventArgs e)
{
    try
    {
        int lastnum = int.Parse(lastText.Text);
        int typenum = int.Parse(typeText.Text);
        lastText.Text = "" + (lastnum / typenum);
        typeText.Text = "0";
    }
    catch
    {
        return;
    }
}

clrButtonClickメソッドを作成

スクリーンショット 2016-05-02 16.45.07

private void clrButtonClick(object sender, EventArgs e)
{
    if (typeText.Text == "0")
    {
        lastText.Text = "0";
    }
    typeText.Text = "0";
}

enterButtonClickメソッドを作成

スクリーンショット 2016-05-02 16.47.49

private void enterButtonClick(object sender, EventArgs e)
{
    string s = typeText.Text;
    lastText.Text = s;
    typeText.Text = "0";
}

作成したコード

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Calculator
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void FormKeyPress(object sender, KeyPressEventArgs e)
        {
            string key = e.KeyChar.ToString();
            int n = 0;
            try
            {
                n = int.Parse(key);
            }
            catch
            {
                return;
            }

            string num = typeText.Text + n;
            try
            {
                typeText.Text = "" + int.Parse(num);
            }
            catch
            {
                return;
            }

        }

        private void plusButtonClick(object sender, EventArgs e)
        {
            try
            {
                int lastnum = int.Parse(lastText.Text);
                int typenum = int.Parse(typeText.Text);
                lastText.Text = "" + (lastnum + typenum);
                typeText.Text = "0";
            }
            catch
            {
                return;
            }
        }

        private void subButtonClick(object sender, EventArgs e)
        {
            try
            {
                int lastnum = int.Parse(lastText.Text);
                int typenum = int.Parse(typeText.Text);
                lastText.Text = "" + (lastnum - typenum);
                typeText.Text = "0";
            }
            catch
            {
                return;
            }

        }

        private void multiButtonClick(object sender, EventArgs e)
        {
            try
            {
                int lastnum = int.Parse(lastText.Text);
                int typenum = int.Parse(typeText.Text);
                lastText.Text = "" + (lastnum * typenum);
                typeText.Text = "0";
            }
            catch
            {
                return;
            }

        }

        private void divButtonClick(object sender, EventArgs e)
        {
            try
            {
                int lastnum = int.Parse(lastText.Text);
                int typenum = int.Parse(typeText.Text);
                lastText.Text = "" + (lastnum / typenum);
                typeText.Text = "0";
            }
            catch
            {
                return;
            }

        }

        private void clrButtonClick(object sender, EventArgs e)
        {
            if (typeText.Text == "0")
            {
                lastText.Text = "0";
            }
            typeText.Text = "0";
        }

        private void enterButtonClick(object sender, EventArgs e)
        {
            string s = typeText.Text;
            lastText.Text = s;
            typeText.Text = "0";
        }
    }
}

My電卓使い方

計算例: 123+456=

まずキーボードから数字123入力

スクリーンショット 2016-05-02 17.01.50

「ER」キーで数字を設定

スクリーンショット 2016-05-02 17.01.53

次の数字456を入力

スクリーンショット 2016-05-02 17.02.00

演算キーで計算

スクリーンショット 2016-05-02 17.02.11